PageRenderTime 727ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/erts/preloaded/src/prim_inet.erl

https://github.com/cobusc/otp
Erlang | 2505 lines | 1719 code | 238 blank | 548 comment | 12 complexity | 0c6571e8d208a25767f00072b03c17fd MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. %%
  2. %% %CopyrightBegin%
  3. %%
  4. %% Copyright Ericsson AB 2000-2017. All Rights Reserved.
  5. %%
  6. %% Licensed under the Apache License, Version 2.0 (the "License");
  7. %% you may not use this file except in compliance with the License.
  8. %% You may obtain a copy of the License at
  9. %%
  10. %% http://www.apache.org/licenses/LICENSE-2.0
  11. %%
  12. %% Unless required by applicable law or agreed to in writing, software
  13. %% distributed under the License is distributed on an "AS IS" BASIS,
  14. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. %% See the License for the specific language governing permissions and
  16. %% limitations under the License.
  17. %%
  18. %% %CopyrightEnd%
  19. %%
  20. %% The SCTP protocol was added 2006
  21. %% by Leonid Timochouk <l.timochouk@gmail.com>
  22. %% and Serge Aleynikov <saleyn@gmail.com>
  23. %% at IDT Corp. Adapted by the OTP team at Ericsson AB.
  24. %%
  25. -module(prim_inet).
  26. %% Primitive inet_drv interface
  27. -export([open/3, open/4, fdopen/4, fdopen/5, close/1]).
  28. -export([bind/3, listen/1, listen/2, peeloff/2]).
  29. -export([connect/3, connect/4, async_connect/4]).
  30. -export([accept/1, accept/2, async_accept/2]).
  31. -export([shutdown/2]).
  32. -export([send/2, send/3, sendto/4, sendmsg/3, sendfile/4]).
  33. -export([recv/2, recv/3, async_recv/3]).
  34. -export([unrecv/2]).
  35. -export([recvfrom/2, recvfrom/3]).
  36. -export([setopt/3, setopts/2, getopt/2, getopts/2, is_sockopt_val/2]).
  37. -export([chgopt/3, chgopts/2]).
  38. -export([getstat/2, getfd/1, ignorefd/2,
  39. getindex/1, getstatus/1, gettype/1,
  40. getifaddrs/1, getiflist/1, ifget/3, ifset/3,
  41. gethostname/1]).
  42. -export([getservbyname/3, getservbyport/3]).
  43. -export([peername/1, setpeername/2, peernames/1, peernames/2]).
  44. -export([sockname/1, setsockname/2, socknames/1, socknames/2]).
  45. -export([attach/1, detach/1]).
  46. -include("inet_sctp.hrl").
  47. -include("inet_int.hrl").
  48. %-define(DEBUG, 1).
  49. -ifdef(DEBUG).
  50. -define(DBG_FORMAT(Format, Args), (io:format((Format), (Args)))).
  51. -else.
  52. -define(DBG_FORMAT(Format, Args), ok).
  53. -endif.
  54. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  55. %%
  56. %% OPEN(tcp | udp | sctp, inet | inet6, stream | dgram | seqpacket) ->
  57. %% {ok, insock()} |
  58. %% {error, Reason}
  59. %%
  60. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  61. open(Protocol, Family, Type) ->
  62. open(Protocol, Family, Type, [], ?INET_REQ_OPEN, []).
  63. open(Protocol, Family, Type, Opts) ->
  64. open(Protocol, Family, Type, Opts, ?INET_REQ_OPEN, []).
  65. %% FDOPEN(tcp|udp|sctp, inet|inet6|local, stream|dgram|seqpacket, integer())
  66. fdopen(Protocol, Family, Type, Fd) when is_integer(Fd) ->
  67. fdopen(Protocol, Family, Type, Fd, true).
  68. fdopen(Protocol, Family, Type, Fd, Bound)
  69. when is_integer(Fd), is_boolean(Bound) ->
  70. open(Protocol, Family, Type, [], ?INET_REQ_FDOPEN,
  71. [?int32(Fd), enc_value_2(bool, Bound)]).
  72. open(Protocol, Family, Type, Opts, Req, Data) ->
  73. Drv = protocol2drv(Protocol),
  74. AF = enc_family(Family),
  75. T = enc_type(Type),
  76. try erlang:open_port({spawn_driver,Drv}, [binary]) of
  77. S ->
  78. case setopts(S, Opts) of
  79. ok ->
  80. case ctl_cmd(S, Req, [AF,T,Data]) of
  81. {ok,_} -> {ok,S};
  82. {error,_}=E1 ->
  83. close(S),
  84. E1
  85. end;
  86. {error,_}=E2 ->
  87. close(S),
  88. E2
  89. end
  90. catch
  91. %% The only (?) way to get here is to try to open
  92. %% the sctp driver when it does not exist (badarg)
  93. error:badarg -> {error, eprotonosupport};
  94. %% system_limit if out of port slots
  95. error:system_limit -> {error, system_limit}
  96. end.
  97. enc_family(inet) -> ?INET_AF_INET;
  98. enc_family(inet6) -> ?INET_AF_INET6;
  99. enc_family(local) -> ?INET_AF_LOCAL.
  100. enc_type(stream) -> ?INET_TYPE_STREAM;
  101. enc_type(dgram) -> ?INET_TYPE_DGRAM;
  102. enc_type(seqpacket) -> ?INET_TYPE_SEQPACKET.
  103. protocol2drv(tcp) -> "tcp_inet";
  104. protocol2drv(udp) -> "udp_inet";
  105. protocol2drv(sctp) -> "sctp_inet".
  106. drv2protocol("tcp_inet") -> tcp;
  107. drv2protocol("udp_inet") -> udp;
  108. drv2protocol("sctp_inet") -> sctp;
  109. drv2protocol(_) -> undefined.
  110. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  111. %%
  112. %% Shutdown(insock(), atom()) -> ok
  113. %%
  114. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  115. %% TODO: shutdown equivalent for SCTP
  116. %%
  117. shutdown(S, read) when is_port(S) ->
  118. shutdown_1(S, 0);
  119. shutdown(S, write) when is_port(S) ->
  120. shutdown_1(S, 1);
  121. shutdown(S, read_write) when is_port(S) ->
  122. shutdown_1(S, 2).
  123. shutdown_1(S, How) ->
  124. case ctl_cmd(S, ?TCP_REQ_SHUTDOWN, [How]) of
  125. {ok, []} -> ok;
  126. {error,_}=Error -> Error
  127. end.
  128. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  129. %%
  130. %% CLOSE(insock()) -> ok
  131. %%
  132. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  133. close(S) when is_port(S) ->
  134. case getopt(S, linger) of
  135. {ok,{true,0}} ->
  136. close_port(S);
  137. _ ->
  138. case subscribe(S, [subs_empty_out_q]) of
  139. {ok, [{subs_empty_out_q,N}]} when N > 0 ->
  140. close_pend_loop(S, N); %% wait for pending output to be sent
  141. _ ->
  142. close_port(S)
  143. end
  144. end.
  145. close_pend_loop(S, N) ->
  146. receive
  147. {empty_out_q,S} ->
  148. close_port(S)
  149. after ?INET_CLOSE_TIMEOUT ->
  150. case getstat(S, [send_pend]) of
  151. {ok, [{send_pend,N1}]} ->
  152. if
  153. N1 =:= N ->
  154. close_port(S);
  155. true ->
  156. close_pend_loop(S, N1)
  157. end;
  158. _ ->
  159. close_port(S)
  160. end
  161. end.
  162. close_port(S) ->
  163. catch erlang:port_close(S),
  164. receive {'EXIT',S,_} -> ok after 0 -> ok end.
  165. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  166. %%
  167. %% BIND(insock(), IP, Port) -> {ok, integer()} | {error, Reason}
  168. %%
  169. %% bind the insock() to the interface address given by IP and Port
  170. %%
  171. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  172. %% Multi-homed "bind": sctp_bindx(). The Op is 'add' or 'remove'.
  173. %% If no addrs are specified, it just does nothing.
  174. %% Function returns {ok, S} on success, unlike TCP/UDP "bind":
  175. bind(S, add, Addrs) when is_port(S), is_list(Addrs) ->
  176. bindx(S, 1, Addrs);
  177. bind(S, remove, Addrs) when is_port(S), is_list(Addrs) ->
  178. bindx(S, 0, Addrs);
  179. bind(S, Addr, _) when is_port(S), tuple_size(Addr) =:= 2 ->
  180. case type_value(set, addr, Addr) of
  181. true ->
  182. case ctl_cmd(S,?INET_REQ_BIND,enc_value(set, addr, Addr)) of
  183. {ok, [P1,P0]} -> {ok, ?u16(P1, P0)};
  184. {error, _} = Error -> Error
  185. end;
  186. false ->
  187. {error, einval}
  188. end;
  189. bind(S, IP, Port) ->
  190. bind(S, {IP, Port}, 0).
  191. bindx(S, AddFlag, Addrs) ->
  192. case getprotocol(S) of
  193. sctp ->
  194. case bindx_check_addrs(Addrs) of
  195. true ->
  196. %% Really multi-homed "bindx". Stringified args:
  197. %% [AddFlag, (AddrBytes see enc_value_2(addr,X))+]:
  198. Args =
  199. [?int8(AddFlag)|
  200. [enc_value(set, addr, Addr) || Addr <- Addrs]],
  201. case ctl_cmd(S, ?SCTP_REQ_BINDX, Args) of
  202. {ok, _} -> {ok, S};
  203. {error, _}=Error -> Error
  204. end;
  205. false ->
  206. {error, einval}
  207. end;
  208. _ ->
  209. {error, einval}
  210. end.
  211. bindx_check_addrs([Addr|Addrs]) ->
  212. type_value(set, addr, Addr) andalso bindx_check_addrs(Addrs);
  213. bindx_check_addrs([]) ->
  214. true.
  215. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  216. %%
  217. %% CONNECT(insock(), IP, Port [,Timeout]) -> ok | {error, Reason}
  218. %%
  219. %% connect the insock() to the address given by IP and Port
  220. %% if timeout is given:
  221. %% timeout < 0 -> infinity
  222. %% 0 -> immediate connect (mostly works for loopback)
  223. %% > 0 -> wait for timeout ms if not connected then
  224. %% return {error, timeout}
  225. %%
  226. %% ASYNC_CONNECT(insock(), IP, Port, Timeout) -> {ok, S, Ref} | {error, Reason}
  227. %%
  228. %% a {inet_async,S,Ref,Status} will be sent on socket condition
  229. %%
  230. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  231. %% For TCP, UDP or SCTP sockets.
  232. %%
  233. connect(S, IP, Port) ->
  234. connect(S, IP, Port, infinity).
  235. %%
  236. connect(S, Addr, _, Time) when is_port(S), tuple_size(Addr) =:= 2 ->
  237. case type_value(set, addr, Addr) of
  238. true when Time =:= infinity ->
  239. connect0(S, Addr, -1);
  240. true when is_integer(Time) ->
  241. connect0(S, Addr, Time);
  242. false ->
  243. {error, einval}
  244. end;
  245. connect(S, IP, Port, Time) ->
  246. connect(S, {IP, Port}, 0, Time).
  247. connect0(S, Addr, Time) ->
  248. case async_connect0(S, Addr, Time) of
  249. {ok, S, Ref} ->
  250. receive
  251. {inet_async, S, Ref, Status} ->
  252. Status
  253. end;
  254. Error -> Error
  255. end.
  256. async_connect(S, Addr, _, Time) when is_port(S), tuple_size(Addr) =:= 2 ->
  257. case type_value(set, addr, Addr) of
  258. true when Time =:= infinity ->
  259. async_connect0(S, Addr, -1);
  260. true when is_integer(Time) ->
  261. async_connect0(S, Addr, Time);
  262. false ->
  263. {error, einval}
  264. end;
  265. %%
  266. async_connect(S, IP, Port, Time) ->
  267. async_connect(S, {IP, Port}, 0, Time).
  268. async_connect0(S, Addr, Time) ->
  269. case ctl_cmd(
  270. S, ?INET_REQ_CONNECT,
  271. [enc_time(Time),enc_value(set, addr, Addr)])
  272. of
  273. {ok, [R1,R0]} -> {ok, S, ?u16(R1,R0)};
  274. {error, _}=Error -> Error
  275. end.
  276. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  277. %%
  278. %% ACCEPT(insock() [,Timeout] ) -> {ok,insock()} | {error, Reason}
  279. %%
  280. %% accept incoming connection on listen socket
  281. %% if timeout is given:
  282. %% timeout < 0 -> infinity
  283. %% 0 -> immediate accept (poll)
  284. %% > 0 -> wait for timeout ms for accept if no accept then
  285. %% return {error, timeout}
  286. %%
  287. %% ASYNC_ACCEPT(insock(), Timeout)
  288. %%
  289. %% async accept. return {ok,S,Ref} or {error, Reason}
  290. %% the owner of socket S will receive an {inet_async,S,Ref,Status} on
  291. %% socket condition
  292. %%
  293. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  294. %% For TCP sockets only.
  295. %%
  296. accept(L) -> accept0(L, -1).
  297. accept(L, infinity) -> accept0(L, -1);
  298. accept(L, Time) -> accept0(L, Time).
  299. accept0(L, Time) when is_port(L), is_integer(Time) ->
  300. case async_accept(L, Time) of
  301. {ok, Ref} ->
  302. receive
  303. {inet_async, L, Ref, {ok,S}} ->
  304. accept_opts(L, S);
  305. {inet_async, L, Ref, Error} ->
  306. Error
  307. end;
  308. Error -> Error
  309. end.
  310. %% setup options from listen socket on the connected socket
  311. accept_opts(L, S) ->
  312. case getopts(L, [active, nodelay, keepalive, delay_send, priority, tos]) of
  313. {ok, Opts} ->
  314. case setopts(S, Opts) of
  315. ok ->
  316. case getopts(L, [tclass]) of
  317. {ok, []} ->
  318. {ok, S};
  319. {ok, TClassOpts} ->
  320. case setopts(S, TClassOpts) of
  321. ok ->
  322. {ok, S};
  323. Error -> close(S), Error
  324. end
  325. end;
  326. Error -> close(S), Error
  327. end;
  328. Error ->
  329. close(S), Error
  330. end.
  331. async_accept(L, Time) ->
  332. case ctl_cmd(L,?INET_REQ_ACCEPT, [enc_time(Time)]) of
  333. {ok, [R1,R0]} -> {ok, ?u16(R1,R0)};
  334. {error,_}=Error -> Error
  335. end.
  336. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  337. %%
  338. %% LISTEN(insock() [,Backlog]) -> ok | {error, Reason}
  339. %%
  340. %% set listen mode on socket
  341. %%
  342. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  343. %% For TCP or SCTP sockets. For SCTP, Boolean backlog value (enable/disable
  344. %% listening) is also accepted:
  345. listen(S) -> listen(S, ?LISTEN_BACKLOG).
  346. listen(S, true) -> listen(S, ?LISTEN_BACKLOG);
  347. listen(S, false) -> listen(S, 0);
  348. listen(S, BackLog) when is_port(S), is_integer(BackLog) ->
  349. case ctl_cmd(S, ?INET_REQ_LISTEN, [?int16(BackLog)]) of
  350. {ok, _} -> ok;
  351. {error,_}=Error -> Error
  352. end.
  353. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  354. %%
  355. %% PEELOFF(insock(), AssocId) -> {ok,outsock()} | {error, Reason}
  356. %%
  357. %% SCTP: Peel off one association into a type stream socket
  358. %%
  359. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  360. peeloff(S, AssocId) ->
  361. case ctl_cmd(S, ?SCTP_REQ_PEELOFF, [?int32(AssocId)]) of
  362. inet_reply ->
  363. receive
  364. {inet_reply,S,Res} -> Res
  365. end;
  366. {error,_}=Error -> Error
  367. end.
  368. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  369. %%
  370. %% SEND(insock(), Data) -> ok | {error, Reason}
  371. %%
  372. %% send Data on the socket (io-list)
  373. %%
  374. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  375. %% This is a generic "port_command" interface used by TCP, UDP, SCTP, depending
  376. %% on the driver it is mapped to, and the "Data". It actually sends out data,--
  377. %% NOT delegating this task to any back-end. For SCTP, this function MUST NOT
  378. %% be called directly -- use "sendmsg" instead:
  379. %%
  380. send(S, Data, OptList) when is_port(S), is_list(OptList) ->
  381. ?DBG_FORMAT("prim_inet:send(~p, ~p)~n", [S,Data]),
  382. try erlang:port_command(S, Data, OptList) of
  383. false -> % Port busy and nosuspend option passed
  384. ?DBG_FORMAT("prim_inet:send() -> {error,busy}~n", []),
  385. {error,busy};
  386. true ->
  387. receive
  388. {inet_reply,S,Status} ->
  389. ?DBG_FORMAT("prim_inet:send() -> ~p~n", [Status]),
  390. Status
  391. end
  392. catch
  393. error:_Error ->
  394. ?DBG_FORMAT("prim_inet:send() -> {error,einval}~n", []),
  395. {error,einval}
  396. end.
  397. send(S, Data) ->
  398. send(S, Data, []).
  399. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  400. %%
  401. %% SENDTO(insock(), IP, Port, Data) -> ok | {error, Reason}
  402. %%
  403. %% send Datagram to the IP at port (Should add sync send!)
  404. %%
  405. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  406. %% "sendto" is for UDP. IP and Port are set by the caller to 0 if the socket
  407. %% is known to be connected.
  408. sendto(S, Addr, _, Data) when is_port(S), tuple_size(Addr) =:= 2 ->
  409. case type_value(set, addr, Addr) of
  410. true ->
  411. ?DBG_FORMAT("prim_inet:sendto(~p, ~p, ~p)~n", [S,Addr,Data]),
  412. try
  413. erlang:port_command(S, [enc_value(set, addr, Addr),Data])
  414. of
  415. true ->
  416. receive
  417. {inet_reply,S,Reply} ->
  418. ?DBG_FORMAT(
  419. "prim_inet:sendto() -> ~p~n", [Reply]),
  420. Reply
  421. end
  422. catch
  423. error:_ ->
  424. ?DBG_FORMAT(
  425. "prim_inet:sendto() -> {error,einval}~n", []),
  426. {error,einval}
  427. end;
  428. false ->
  429. ?DBG_FORMAT(
  430. "prim_inet:sendto() -> {error,einval}~n", []),
  431. {error,einval}
  432. end;
  433. sendto(S, IP, Port, Data) ->
  434. sendto(S, {IP, Port}, 0, Data).
  435. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  436. %%
  437. %% SENDMSG(insock(), IP, Port, InitMsg, Data) or
  438. %% SENDMSG(insock(), SndRcvInfo, Data) -> ok | {error, Reason}
  439. %%
  440. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  441. %% SCTP: Sending data over an existing association: no need for a destination
  442. %% addr; uses SndRcvInfo:
  443. %%
  444. sendmsg(S, #sctp_sndrcvinfo{}=SRI, Data) when is_port(S) ->
  445. Type = type_opt(set, sctp_default_send_param),
  446. try type_value(set, Type, SRI) of
  447. true ->
  448. send(S, [enc_value(set, Type, SRI)|Data]);
  449. false -> {error,einval}
  450. catch
  451. Reason -> {error,Reason}
  452. end.
  453. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  454. %%
  455. %% SENDFILE(outsock(), Fd, Offset, Length) -> {ok,BytesSent} | {error, Reason}
  456. %%
  457. %% send Length data bytes from a file handle, to a socket, starting at Offset
  458. %%
  459. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  460. %% "sendfile" is for TCP:
  461. sendfile(S, FileHandle, Offset, Length)
  462. when not is_port(S);
  463. not is_binary(FileHandle);
  464. not is_integer(Offset);
  465. not is_integer(Length) ->
  466. {error, badarg};
  467. sendfile(S, FileHandle, Offset, Length) ->
  468. case erlang:port_info(S, connected) of
  469. {connected, Pid} when Pid =:= self() ->
  470. sendfile_1(S, FileHandle, Offset, Length);
  471. {connected, Pid} when Pid =/= self() ->
  472. {error, not_owner};
  473. _Other ->
  474. {error, einval}
  475. end.
  476. sendfile_1(S, FileHandle, Offset, 0) ->
  477. sendfile_1(S, FileHandle, Offset, (1 bsl 63) - 1);
  478. sendfile_1(_S, _FileHandle, Offset, Length) when
  479. Offset < 0; Offset > ((1 bsl 63) - 1);
  480. Length < 0; Length > ((1 bsl 63) - 1) ->
  481. {error, einval};
  482. sendfile_1(S, FileHandle, Offset, Length) ->
  483. Args = [FileHandle,
  484. ?int64(Offset),
  485. ?int64(Length)],
  486. case ctl_cmd(S, ?TCP_REQ_SENDFILE, Args) of
  487. {ok, []} ->
  488. receive
  489. {sendfile, S, {ok, SentLow, SentHigh}} ->
  490. {ok, SentLow bor (SentHigh bsl 32)};
  491. {sendfile, S, {error, Reason}} ->
  492. {error, Reason};
  493. {'EXIT', S, _Reason} ->
  494. {error, closed}
  495. end;
  496. {error, Reason} ->
  497. {error, Reason}
  498. end.
  499. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  500. %%
  501. %% RECV(insock(), Length, [Timeout]) -> {ok,Data} | {error, Reason}
  502. %%
  503. %% receive Length data bytes from a socket
  504. %% if 0 is given then a Data packet is requested (see setopt (packet))
  505. %% N read N bytes
  506. %%
  507. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  508. %% "recv" is for TCP:
  509. recv(S, Length) -> recv0(S, Length, -1).
  510. recv(S, Length, infinity) -> recv0(S, Length,-1);
  511. recv(S, Length, Time) when is_integer(Time) -> recv0(S, Length, Time).
  512. recv0(S, Length, Time) when is_port(S), is_integer(Length), Length >= 0 ->
  513. case async_recv(S, Length, Time) of
  514. {ok, Ref} ->
  515. receive
  516. {inet_async, S, Ref, Status} -> Status;
  517. {'EXIT', S, _Reason} ->
  518. {error, closed}
  519. end;
  520. Error -> Error
  521. end.
  522. async_recv(S, Length, Time) ->
  523. case ctl_cmd(S, ?TCP_REQ_RECV, [enc_time(Time), ?int32(Length)]) of
  524. {ok,[R1,R0]} -> {ok, ?u16(R1,R0)};
  525. {error,_}=Error -> Error
  526. end.
  527. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  528. %%
  529. %% RECVFROM(insock(), Lenth [Timeout]) -> {ok,{IP,Port,Data}} | {error, Reason}
  530. %% For SCTP: -> {ok,{IP,Port,[AncData],Data}}
  531. %% | {error, Reason}
  532. %% receive Length data bytes from a datagram socket sent from IP at Port
  533. %% if 0 is given then a Data packet is requested (see setopt (packet))
  534. %% N read N bytes
  535. %%
  536. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  537. %% "recvfrom" is for both UDP and SCTP.
  538. %% NB: "Length" is actually ignored for these protocols, since they are msg-
  539. %% oriented: preserved here only for API compatibility.
  540. %%
  541. recvfrom(S, Length) ->
  542. recvfrom(S, Length, infinity).
  543. recvfrom(S, Length, infinity) when is_port(S) ->
  544. recvfrom0(S, Length, -1);
  545. recvfrom(S, Length, Time) when is_port(S) ->
  546. if
  547. is_integer(Time), 0 =< Time, Time < 16#ffffffff ->
  548. recvfrom0(S, Length, Time);
  549. true ->
  550. {error, einval}
  551. end.
  552. recvfrom0(S, Length, Time)
  553. when is_integer(Length), 0 =< Length, Length =< 16#ffffffff ->
  554. case ctl_cmd(S, ?PACKET_REQ_RECV,[enc_time(Time),?int32(Length)]) of
  555. {ok,[R1,R0]} ->
  556. Ref = ?u16(R1,R0),
  557. receive
  558. % Success, UDP:
  559. {inet_async, S, Ref, {ok, [F | AddrData]}} ->
  560. case get_addr(F, AddrData) of
  561. {{Family, _} = Addr, Data} when is_atom(Family) ->
  562. {ok, {Addr, 0, Data}};
  563. {{IP, Port}, Data} ->
  564. {ok, {IP, Port, Data}}
  565. end;
  566. % Success, SCTP:
  567. {inet_async, S, Ref, {ok, {[F,P1,P0 | Addr], AncData, DE}}} ->
  568. {IP, _} = get_ip(F, Addr),
  569. {ok, {IP, ?u16(P1, P0), AncData, DE}};
  570. % Back-end error:
  571. {inet_async, S, Ref, Error={error, _}} ->
  572. Error
  573. end;
  574. {error,_}=Error ->
  575. Error % Front-end error
  576. end;
  577. recvfrom0(_, _, _) -> {error,einval}.
  578. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  579. %%
  580. %% PEERNAME(insock()) -> {ok, {IP, Port}} | {error, Reason}
  581. %%
  582. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  583. peername(S) when is_port(S) ->
  584. case ctl_cmd(S, ?INET_REQ_PEER, []) of
  585. {ok, [F | Addr]} ->
  586. {A, _} = get_addr(F, Addr),
  587. {ok, A};
  588. {error, _} = Error -> Error
  589. end.
  590. setpeername(S, undefined) when is_port(S) ->
  591. case ctl_cmd(S, ?INET_REQ_SETPEER, []) of
  592. {ok, []} -> ok;
  593. {error, _} = Error -> Error
  594. end;
  595. setpeername(S, Addr) when is_port(S) ->
  596. case type_value(set, addr, Addr) of
  597. true ->
  598. case ctl_cmd(S, ?INET_REQ_SETPEER, enc_value(set, addr, Addr)) of
  599. {ok, []} -> ok;
  600. {error, _} = Error -> Error
  601. end;
  602. false ->
  603. {error, einval}
  604. end.
  605. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  606. %%
  607. %% PEERNAMES(insock()) -> {ok, [{IP, Port}, ...]} | {error, Reason}
  608. %%
  609. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  610. peernames(S) when is_port(S) ->
  611. peernames(S, undefined).
  612. peernames(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
  613. peernames(S, AssocId);
  614. peernames(S, AssocId)
  615. when is_port(S), is_integer(AssocId);
  616. is_port(S), AssocId =:= undefined ->
  617. Q = get,
  618. Type = [[sctp_assoc_id,0]],
  619. case type_value(Q, Type, AssocId) of
  620. true ->
  621. case ctl_cmd
  622. (S, ?INET_REQ_GETPADDRS,
  623. enc_value(Q, Type, AssocId)) of
  624. {ok,Addrs} ->
  625. {ok,get_addrs(Addrs)};
  626. Error ->
  627. Error
  628. end;
  629. false ->
  630. {error,einval}
  631. end.
  632. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  633. %%
  634. %% SOCKNAME(insock()) -> {ok, {IP, Port}} | {error, Reason}
  635. %%
  636. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  637. sockname(S) when is_port(S) ->
  638. case ctl_cmd(S, ?INET_REQ_NAME, []) of
  639. {ok, [F | Addr]} ->
  640. {A, _} = get_addr(F, Addr),
  641. {ok, A};
  642. {error, _} = Error -> Error
  643. end.
  644. setsockname(S, undefined) when is_port(S) ->
  645. case ctl_cmd(S, ?INET_REQ_SETNAME, []) of
  646. {ok, []} -> ok;
  647. {error, _} = Error -> Error
  648. end;
  649. setsockname(S, Addr) when is_port(S) ->
  650. case type_value(set, addr, Addr) of
  651. true ->
  652. case
  653. ctl_cmd(S, ?INET_REQ_SETNAME, enc_value(set, addr, Addr))
  654. of
  655. {ok, []} -> ok;
  656. {error, _} = Error -> Error
  657. end;
  658. false ->
  659. {error, einval}
  660. end.
  661. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  662. %%
  663. %% SOCKNAMES(insock()) -> {ok, [{IP, Port}, ...]} | {error, Reason}
  664. %%
  665. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  666. socknames(S) when is_port(S) ->
  667. socknames(S, undefined).
  668. socknames(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
  669. socknames(S, AssocId);
  670. socknames(S, AssocId)
  671. when is_port(S), is_integer(AssocId);
  672. is_port(S), AssocId =:= undefined ->
  673. Q = get,
  674. Type = [[sctp_assoc_id,0]],
  675. case type_value(Q, Type, AssocId) of
  676. true ->
  677. case ctl_cmd
  678. (S, ?INET_REQ_GETLADDRS,
  679. enc_value(Q, Type, AssocId)) of
  680. {ok,Addrs} ->
  681. {ok,get_addrs(Addrs)};
  682. Error ->
  683. Error
  684. end;
  685. false ->
  686. {error,einval}
  687. end.
  688. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  689. %%
  690. %% SETOPT(insock(), Opt, Value) -> ok | {error, Reason}
  691. %% SETOPTS(insock(), [{Opt,Value}]) -> ok | {error, Reason}
  692. %%
  693. %% set socket, ip and driver option
  694. %%
  695. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  696. setopt(S, Opt, Value) when is_port(S) ->
  697. setopts(S, [{Opt,Value}]).
  698. setopts(S, Opts) when is_port(S) ->
  699. case encode_opt_val(Opts) of
  700. {ok, Buf} ->
  701. case ctl_cmd(S, ?INET_REQ_SETOPTS, Buf) of
  702. {ok, _} -> ok;
  703. {error,_}=Error -> Error
  704. end;
  705. Error -> Error
  706. end.
  707. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  708. %%
  709. %% GETOPT(insock(), Opt) -> {ok,Value} | {error, Reason}
  710. %% GETOPTS(insock(), [Opt]) -> {ok, [{Opt,Value}]} | {error, Reason}
  711. %% get socket, ip and driver option
  712. %%
  713. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  714. getopt(S, Opt) when is_port(S), is_atom(Opt) ->
  715. case getopts(S, [Opt]) of
  716. {ok,[{_,Value}]} -> {ok, Value};
  717. Error -> Error
  718. end.
  719. getopts(S, Opts) when is_port(S), is_list(Opts) ->
  720. case encode_opts(Opts) of
  721. {ok,Buf} ->
  722. case ctl_cmd(S, ?INET_REQ_GETOPTS, Buf) of
  723. {ok,Rep} ->
  724. %% Non-SCTP: "Rep" contains the encoded option vals:
  725. decode_opt_val(Rep);
  726. inet_reply ->
  727. %% SCTP: Need to receive the full value:
  728. receive
  729. {inet_reply,S,Res} -> Res
  730. end;
  731. {error,_}=Error -> Error
  732. end;
  733. Error -> Error
  734. end.
  735. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  736. %%
  737. %% CHGOPT(insock(), Opt) -> {ok,Value} | {error, Reason}
  738. %% CHGOPTS(insock(), [Opt]) -> {ok, [{Opt,Value}]} | {error, Reason}
  739. %% change socket, ip and driver option
  740. %%
  741. %% Same as setopts except for record value options where undefined
  742. %% fields are read with getopts before setting.
  743. %%
  744. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  745. chgopt(S, Opt, Value) when is_port(S) ->
  746. chgopts(S, [{Opt,Value}]).
  747. chgopts(S, Opts) when is_port(S), is_list(Opts) ->
  748. case getopts(S, need_template(Opts)) of
  749. {ok,Templates} ->
  750. try merge_options(Opts, Templates) of
  751. NewOpts ->
  752. setopts(S, NewOpts)
  753. catch
  754. Reason -> {error,Reason}
  755. end;
  756. Error -> Error
  757. end.
  758. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  759. %%
  760. %% getifaddrs(insock()) -> {ok,IfAddrsList} | {error, Reason}
  761. %%
  762. %% IfAddrsList = [{Name,[Opts]}]
  763. %% Name = string()
  764. %% Opts = {flags,[Flag]} | {addr,Addr} | {netmask,Addr} | {broadaddr,Addr}
  765. %% | {dstaddr,Addr} | {hwaddr,HwAddr} | {mtu,integer()}
  766. %% Flag = up | broadcast | loopback | running | multicast
  767. %% Addr = ipv4addr() | ipv6addr()
  768. %% HwAddr = ethernet_addr()
  769. %%
  770. %% get interface name and addresses list
  771. %%
  772. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  773. getifaddrs(S) when is_port(S) ->
  774. case ctl_cmd(S, ?INET_REQ_GETIFADDRS, []) of
  775. {ok, Data} ->
  776. {ok, comp_ifaddrs(build_ifaddrs(Data), ktree_empty())};
  777. {error,enotsup} ->
  778. case getiflist(S) of
  779. {ok, IFs} ->
  780. {ok, getifaddrs_ifget(S, IFs)};
  781. Err1 -> Err1
  782. end;
  783. Err2 -> Err2
  784. end.
  785. %% Restructure interface properties per interface and remove duplicates
  786. comp_ifaddrs([{If,Opts}|IfOpts], T) ->
  787. case ktree_is_defined(If, T) of
  788. true ->
  789. OptSet = comp_ifaddrs_add(ktree_get(If, T), Opts),
  790. comp_ifaddrs(IfOpts, ktree_update(If, OptSet, T));
  791. false ->
  792. OptSet = comp_ifaddrs_add(ktree_empty(), Opts),
  793. comp_ifaddrs(IfOpts, ktree_insert(If, OptSet, T))
  794. end;
  795. comp_ifaddrs([], T) ->
  796. [{If,ktree_keys(ktree_get(If, T))} || If <- ktree_keys(T)].
  797. comp_ifaddrs_add(OptSet, [Opt|Opts]) ->
  798. case ktree_is_defined(Opt, OptSet) of
  799. true
  800. when element(1, Opt) =:= flags;
  801. element(1, Opt) =:= hwaddr ->
  802. comp_ifaddrs_add(OptSet, Opts);
  803. _ ->
  804. comp_ifaddrs_add(ktree_insert(Opt, undefined, OptSet), Opts)
  805. end;
  806. comp_ifaddrs_add(OptSet, []) -> OptSet.
  807. %% Legacy emulation of getifaddrs
  808. getifaddrs_ifget(_, []) -> [];
  809. getifaddrs_ifget(S, [IF|IFs]) ->
  810. case ifget(S, IF, [flags]) of
  811. {ok,[{flags,Flags}]=FlagsVals} ->
  812. BroadOpts =
  813. case member(broadcast, Flags) of
  814. true ->
  815. [broadaddr,hwaddr];
  816. false ->
  817. [hwaddr]
  818. end,
  819. P2POpts =
  820. case member(pointtopoint, Flags) of
  821. true ->
  822. [dstaddr|BroadOpts];
  823. false ->
  824. BroadOpts
  825. end,
  826. getifaddrs_ifget(S, IFs, IF, FlagsVals, [addr,netmask|P2POpts]);
  827. _ ->
  828. getifaddrs_ifget(S, IFs, IF, [], [addr,netmask,hwaddr])
  829. end.
  830. getifaddrs_ifget(S, IFs, IF, FlagsVals, Opts) ->
  831. OptVals =
  832. case ifget(S, IF, Opts) of
  833. {ok,OVs} -> OVs;
  834. _ -> []
  835. end,
  836. [{IF,FlagsVals++OptVals}|getifaddrs_ifget(S, IFs)].
  837. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  838. %%
  839. %% getiflist(insock()) -> {ok,IfNameList} | {error, Reason}
  840. %%
  841. %% get interface name list
  842. %%
  843. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  844. getiflist(S) when is_port(S) ->
  845. case ctl_cmd(S, ?INET_REQ_GETIFLIST, []) of
  846. {ok, Data} -> {ok, build_iflist(Data)};
  847. {error,_}=Error -> Error
  848. end.
  849. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  850. %%
  851. %% ifget(insock(), IFOpts) -> {ok,IfNameList} | {error, Reason}
  852. %%
  853. %% get interface name list
  854. %%
  855. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  856. ifget(S, Name, Opts) ->
  857. case encode_ifname(Name) of
  858. {ok, Buf1} ->
  859. case encode_ifopts(Opts,[]) of
  860. {ok, Buf2} ->
  861. case ctl_cmd(S, ?INET_REQ_IFGET, [Buf1,Buf2]) of
  862. {ok, Data} -> decode_ifopts(Data,[]);
  863. {error,_}=Error -> Error
  864. end;
  865. Error -> Error
  866. end;
  867. Error -> Error
  868. end.
  869. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  870. %%
  871. %% ifset(insock(), Name, IFOptVals) -> {ok,IfNameList} | {error, Reason}
  872. %%
  873. %% set interface parameters
  874. %%
  875. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  876. ifset(S, Name, Opts) ->
  877. case encode_ifname(Name) of
  878. {ok, Buf1} ->
  879. case encode_ifopt_val(Opts,[]) of
  880. {ok, Buf2} ->
  881. case ctl_cmd(S, ?INET_REQ_IFSET, [Buf1,Buf2]) of
  882. {ok, _} -> ok;
  883. {error,_}=Error -> Error
  884. end;
  885. Error -> Error
  886. end;
  887. Error -> Error
  888. end.
  889. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  890. %%
  891. %% subscribe(insock(), SubsList) -> {ok,StatReply} | {error, Reason}
  892. %%
  893. %% Subscribe on socket events (from driver)
  894. %%
  895. %% Available event subscriptions:
  896. %% subs_empty_out_q: StatReply = [{subs_empty_out_q, N}], where N
  897. %% is current queue length. When the queue becomes empty
  898. %% a {empty_out_q, insock()} message will be sent to
  899. %% subscribing process and the subscription will be
  900. %% removed. If N = 0, the queue is empty and no
  901. %% subscription is made.
  902. %%
  903. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  904. subscribe(S, Sub) when is_port(S), is_list(Sub) ->
  905. case encode_subs(Sub) of
  906. {ok, Bytes} ->
  907. case ctl_cmd(S, ?INET_REQ_SUBSCRIBE, Bytes) of
  908. {ok, Data} -> decode_subs(Data);
  909. {error,_}=Error -> Error
  910. end;
  911. Error -> Error
  912. end.
  913. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  914. %%
  915. %% GETSTAT(insock(), StatList) -> {ok,StatReply} | {error, Reason}
  916. %%
  917. %% get socket statistics (from driver)
  918. %%
  919. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  920. getstat(S, Stats) when is_port(S), is_list(Stats) ->
  921. case encode_stats(Stats) of
  922. {ok, Bytes} ->
  923. case ctl_cmd(S, ?INET_REQ_GETSTAT, Bytes) of
  924. {ok, Data} -> decode_stats(Data);
  925. {error,_}=Error -> Error
  926. end;
  927. Error -> Error
  928. end.
  929. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  930. %%
  931. %% GETFD(insock()) -> {ok,integer()} | {error, Reason}
  932. %%
  933. %% get internal file descriptor
  934. %%
  935. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  936. getfd(S) when is_port(S) ->
  937. case ctl_cmd(S, ?INET_REQ_GETFD, []) of
  938. {ok, [S3,S2,S1,S0]} -> {ok, ?u32(S3,S2,S1,S0)};
  939. {error,_}=Error -> Error
  940. end.
  941. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  942. %%
  943. %% IGNOREFD(insock(),boolean()) -> {ok,integer()} | {error, Reason}
  944. %%
  945. %% steal internal file descriptor
  946. %%
  947. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  948. ignorefd(S,Bool) when is_port(S) ->
  949. Val = if Bool -> 1; true -> 0 end,
  950. case ctl_cmd(S, ?INET_REQ_IGNOREFD, [Val]) of
  951. {ok, _} -> ok;
  952. Error -> Error
  953. end.
  954. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  955. %%
  956. %% GETIX(insock()) -> {ok,integer()} | {error, Reason}
  957. %%
  958. %% get internal socket index
  959. %%
  960. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  961. getindex(S) when is_port(S) ->
  962. %% NOT USED ANY MORE
  963. {error, einval}.
  964. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  965. %%
  966. %% GETTYPE(insock()) -> {ok,{Family,Type}} | {error, Reason}
  967. %%
  968. %% get family/type of a socket
  969. %%
  970. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  971. gettype(S) when is_port(S) ->
  972. case ctl_cmd(S, ?INET_REQ_GETTYPE, []) of
  973. {ok, [F3,F2,F1,F0,T3,T2,T1,T0]} ->
  974. Family = case ?u32(F3,F2,F1,F0) of
  975. ?INET_AF_INET -> inet;
  976. ?INET_AF_INET6 -> inet6;
  977. _ -> undefined
  978. end,
  979. Type = case ?u32(T3,T2,T1,T0) of
  980. ?INET_TYPE_STREAM -> stream;
  981. ?INET_TYPE_DGRAM -> dgram;
  982. ?INET_TYPE_SEQPACKET -> seqpacket;
  983. _ -> undefined
  984. end,
  985. {ok, {Family, Type}};
  986. {error,_}=Error -> Error
  987. end.
  988. getprotocol(S) when is_port(S) ->
  989. {name,Drv} = erlang:port_info(S, name),
  990. drv2protocol(Drv).
  991. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  992. %% IS_SCTP(insock()) -> true | false
  993. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  994. %% is_sctp(S) when is_port(S) ->
  995. %% case gettype(S) of
  996. %% {ok, {_, seqpacket}} -> true;
  997. %% _ -> false
  998. %% end.
  999. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1000. %%
  1001. %% GETSTATUS(insock()) -> {ok,Status} | {error, Reason}
  1002. %%
  1003. %% get socket status
  1004. %%
  1005. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1006. getstatus(S) when is_port(S) ->
  1007. case ctl_cmd(S, ?INET_REQ_GETSTATUS, []) of
  1008. {ok, [S3,S2,S1,S0]} ->
  1009. {ok, dec_status(?u32(S3,S2,S1,S0))};
  1010. {error,_}=Error -> Error
  1011. end.
  1012. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1013. %%
  1014. %% GETHOSTNAME(insock()) -> {ok,HostName} | {error, Reason}
  1015. %%
  1016. %% get host name
  1017. %%
  1018. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1019. gethostname(S) when is_port(S) ->
  1020. ctl_cmd(S, ?INET_REQ_GETHOSTNAME, []).
  1021. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1022. %%
  1023. %% GETSERVBYNAME(insock(),Name,Proto) -> {ok,Port} | {error, Reason}
  1024. %%
  1025. %% get service port
  1026. %%
  1027. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1028. getservbyname(S,Name,Proto) when is_port(S), is_atom(Name), is_atom(Proto) ->
  1029. getservbyname1(S, atom_to_list(Name), atom_to_list(Proto));
  1030. getservbyname(S,Name,Proto) when is_port(S), is_atom(Name), is_list(Proto) ->
  1031. getservbyname1(S, atom_to_list(Name), Proto);
  1032. getservbyname(S,Name,Proto) when is_port(S), is_list(Name), is_atom(Proto) ->
  1033. getservbyname1(S, Name, atom_to_list(Proto));
  1034. getservbyname(S,Name,Proto) when is_port(S), is_list(Name), is_list(Proto) ->
  1035. getservbyname1(S, Name, Proto);
  1036. getservbyname(_,_, _) ->
  1037. {error, einval}.
  1038. getservbyname1(S,Name,Proto) ->
  1039. L1 = length(Name),
  1040. L2 = length(Proto),
  1041. if L1 > 255 -> {error, einval};
  1042. L2 > 255 -> {error, einval};
  1043. true ->
  1044. case ctl_cmd(S, ?INET_REQ_GETSERVBYNAME, [L1,Name,L2,Proto]) of
  1045. {ok, [P1,P0]} ->
  1046. {ok, ?u16(P1,P0)};
  1047. {error,_}=Error ->
  1048. Error
  1049. end
  1050. end.
  1051. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1052. %%
  1053. %% GETSERVBYPORT(insock(),Port,Proto) -> {ok,Port} | {error, Reason}
  1054. %%
  1055. %% get service port from portnumber and protocol
  1056. %%
  1057. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1058. getservbyport(S,Port,Proto) when is_port(S), is_atom(Proto) ->
  1059. getservbyport1(S, Port, atom_to_list(Proto));
  1060. getservbyport(S,Port,Proto) when is_port(S), is_list(Proto) ->
  1061. getservbyport1(S, Port, Proto);
  1062. getservbyport(_, _, _) ->
  1063. {error, einval}.
  1064. getservbyport1(S,Port,Proto) ->
  1065. L = length(Proto),
  1066. if Port < 0 -> {error, einval};
  1067. Port > 16#ffff -> {error, einval};
  1068. L > 255 -> {error, einval};
  1069. true ->
  1070. case ctl_cmd(S, ?INET_REQ_GETSERVBYPORT, [?int16(Port),L,Proto]) of
  1071. {ok, Name} -> {ok, Name};
  1072. {error,_}=Error -> Error
  1073. end
  1074. end.
  1075. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1076. %%
  1077. %% UNRECV(insock(), data) -> ok | {error, Reason}
  1078. %%
  1079. %%
  1080. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1081. unrecv(S, Data) ->
  1082. case ctl_cmd(S, ?TCP_REQ_UNRECV, Data) of
  1083. {ok, _} -> ok;
  1084. {error,_}=Error -> Error
  1085. end.
  1086. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1087. %%
  1088. %% DETACH(insock()) -> ok
  1089. %%
  1090. %% unlink from a socket
  1091. %%
  1092. %% ATTACH(insock()) -> ok | {error, Reason}
  1093. %%
  1094. %% link and connect to a socket
  1095. %%
  1096. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1097. detach(S) when is_port(S) ->
  1098. unlink(S),
  1099. ok.
  1100. attach(S) when is_port(S) ->
  1101. try erlang:port_connect(S, self()) of
  1102. true -> link(S), ok
  1103. catch
  1104. error:Reason -> {error,Reason}
  1105. end.
  1106. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1107. %%
  1108. %% INTERNAL FUNCTIONS
  1109. %%
  1110. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1111. is_sockopt_val(Opt, Val) ->
  1112. Type = type_opt(set, Opt),
  1113. try type_value(set, Type, Val)
  1114. catch
  1115. _ -> false
  1116. end.
  1117. %%
  1118. %% Socket options processing: Encoding option NAMES:
  1119. %%
  1120. enc_opt(reuseaddr) -> ?INET_OPT_REUSEADDR;
  1121. enc_opt(keepalive) -> ?INET_OPT_KEEPALIVE;
  1122. enc_opt(dontroute) -> ?INET_OPT_DONTROUTE;
  1123. enc_opt(linger) -> ?INET_OPT_LINGER;
  1124. enc_opt(broadcast) -> ?INET_OPT_BROADCAST;
  1125. enc_opt(sndbuf) -> ?INET_OPT_SNDBUF;
  1126. enc_opt(recbuf) -> ?INET_OPT_RCVBUF;
  1127. enc_opt(priority) -> ?INET_OPT_PRIORITY;
  1128. enc_opt(tos) -> ?INET_OPT_TOS;
  1129. enc_opt(tclass) -> ?INET_OPT_TCLASS;
  1130. enc_opt(nodelay) -> ?TCP_OPT_NODELAY;
  1131. enc_opt(multicast_if) -> ?UDP_OPT_MULTICAST_IF;
  1132. enc_opt(multicast_ttl) -> ?UDP_OPT_MULTICAST_TTL;
  1133. enc_opt(multicast_loop) -> ?UDP_OPT_MULTICAST_LOOP;
  1134. enc_opt(add_membership) -> ?UDP_OPT_ADD_MEMBERSHIP;
  1135. enc_opt(drop_membership) -> ?UDP_OPT_DROP_MEMBERSHIP;
  1136. enc_opt(ipv6_v6only) -> ?INET_OPT_IPV6_V6ONLY;
  1137. enc_opt(buffer) -> ?INET_LOPT_BUFFER;
  1138. enc_opt(header) -> ?INET_LOPT_HEADER;
  1139. enc_opt(active) -> ?INET_LOPT_ACTIVE;
  1140. enc_opt(packet) -> ?INET_LOPT_PACKET;
  1141. enc_opt(mode) -> ?INET_LOPT_MODE;
  1142. enc_opt(deliver) -> ?INET_LOPT_DELIVER;
  1143. enc_opt(exit_on_close) -> ?INET_LOPT_EXITONCLOSE;
  1144. enc_opt(high_watermark) -> ?INET_LOPT_TCP_HIWTRMRK;
  1145. enc_opt(low_watermark) -> ?INET_LOPT_TCP_LOWTRMRK;
  1146. enc_opt(high_msgq_watermark) -> ?INET_LOPT_MSGQ_HIWTRMRK;
  1147. enc_opt(low_msgq_watermark) -> ?INET_LOPT_MSGQ_LOWTRMRK;
  1148. enc_opt(send_timeout) -> ?INET_LOPT_TCP_SEND_TIMEOUT;
  1149. enc_opt(send_timeout_close) -> ?INET_LOPT_TCP_SEND_TIMEOUT_CLOSE;
  1150. enc_opt(delay_send) -> ?INET_LOPT_TCP_DELAY_SEND;
  1151. enc_opt(packet_size) -> ?INET_LOPT_PACKET_SIZE;
  1152. enc_opt(read_packets) -> ?INET_LOPT_READ_PACKETS;
  1153. enc_opt(netns) -> ?INET_LOPT_NETNS;
  1154. enc_opt(show_econnreset) -> ?INET_LOPT_TCP_SHOW_ECONNRESET;
  1155. enc_opt(line_delimiter) -> ?INET_LOPT_LINE_DELIM;
  1156. enc_opt(raw) -> ?INET_OPT_RAW;
  1157. enc_opt(bind_to_device) -> ?INET_OPT_BIND_TO_DEVICE;
  1158. % Names of SCTP opts:
  1159. enc_opt(sctp_rtoinfo) -> ?SCTP_OPT_RTOINFO;
  1160. enc_opt(sctp_associnfo) -> ?SCTP_OPT_ASSOCINFO;
  1161. enc_opt(sctp_initmsg) -> ?SCTP_OPT_INITMSG;
  1162. enc_opt(sctp_autoclose) -> ?SCTP_OPT_AUTOCLOSE;
  1163. enc_opt(sctp_nodelay) -> ?SCTP_OPT_NODELAY;
  1164. enc_opt(sctp_disable_fragments) -> ?SCTP_OPT_DISABLE_FRAGMENTS;
  1165. enc_opt(sctp_i_want_mapped_v4_addr)-> ?SCTP_OPT_I_WANT_MAPPED_V4_ADDR;
  1166. enc_opt(sctp_maxseg) -> ?SCTP_OPT_MAXSEG;
  1167. enc_opt(sctp_set_peer_primary_addr)-> ?SCTP_OPT_SET_PEER_PRIMARY_ADDR;
  1168. enc_opt(sctp_primary_addr) -> ?SCTP_OPT_PRIMARY_ADDR;
  1169. enc_opt(sctp_adaptation_layer) -> ?SCTP_OPT_ADAPTATION_LAYER;
  1170. enc_opt(sctp_peer_addr_params) -> ?SCTP_OPT_PEER_ADDR_PARAMS;
  1171. enc_opt(sctp_default_send_param) -> ?SCTP_OPT_DEFAULT_SEND_PARAM;
  1172. enc_opt(sctp_events) -> ?SCTP_OPT_EVENTS;
  1173. enc_opt(sctp_delayed_ack_time) -> ?SCTP_OPT_DELAYED_ACK_TIME;
  1174. enc_opt(sctp_status) -> ?SCTP_OPT_STATUS;
  1175. enc_opt(sctp_get_peer_addr_info) -> ?SCTP_OPT_GET_PEER_ADDR_INFO.
  1176. %%
  1177. %%
  1178. %% Decoding option NAMES:
  1179. %%
  1180. dec_opt(?INET_OPT_REUSEADDR) -> reuseaddr;
  1181. dec_opt(?INET_OPT_KEEPALIVE) -> keepalive;
  1182. dec_opt(?INET_OPT_DONTROUTE) -> dontroute;
  1183. dec_opt(?INET_OPT_LINGER) -> linger;
  1184. dec_opt(?INET_OPT_BROADCAST) -> broadcast;
  1185. dec_opt(?INET_OPT_SNDBUF) -> sndbuf;
  1186. dec_opt(?INET_OPT_RCVBUF) -> recbuf;
  1187. dec_opt(?INET_OPT_PRIORITY) -> priority;
  1188. dec_opt(?INET_OPT_TOS) -> tos;
  1189. dec_opt(?INET_OPT_TCLASS) -> tclass;
  1190. dec_opt(?TCP_OPT_NODELAY) -> nodelay;
  1191. dec_opt(?UDP_OPT_MULTICAST_IF) -> multicast_if;
  1192. dec_opt(?UDP_OPT_MULTICAST_TTL) -> multicast_ttl;
  1193. dec_opt(?UDP_OPT_MULTICAST_LOOP) -> multicast_loop;
  1194. dec_opt(?UDP_OPT_ADD_MEMBERSHIP) -> add_membership;
  1195. dec_opt(?UDP_OPT_DROP_MEMBERSHIP) -> drop_membership;
  1196. dec_opt(?INET_OPT_IPV6_V6ONLY) -> ipv6_v6only;
  1197. dec_opt(?INET_LOPT_BUFFER) -> buffer;
  1198. dec_opt(?INET_LOPT_HEADER) -> header;
  1199. dec_opt(?INET_LOPT_ACTIVE) -> active;
  1200. dec_opt(?INET_LOPT_PACKET) -> packet;
  1201. dec_opt(?INET_LOPT_MODE) -> mode;
  1202. dec_opt(?INET_LOPT_DELIVER) -> deliver;
  1203. dec_opt(?INET_LOPT_EXITONCLOSE) -> exit_on_close;
  1204. dec_opt(?INET_LOPT_TCP_HIWTRMRK) -> high_watermark;
  1205. dec_opt(?INET_LOPT_TCP_LOWTRMRK) -> low_watermark;
  1206. dec_opt(?INET_LOPT_MSGQ_HIWTRMRK) -> high_msgq_watermark;
  1207. dec_opt(?INET_LOPT_MSGQ_LOWTRMRK) -> low_msgq_watermark;
  1208. dec_opt(?INET_LOPT_TCP_SEND_TIMEOUT) -> send_timeout;
  1209. dec_opt(?INET_LOPT_TCP_SEND_TIMEOUT_CLOSE) -> send_timeout_close;
  1210. dec_opt(?INET_LOPT_TCP_DELAY_SEND) -> delay_send;
  1211. dec_opt(?INET_LOPT_PACKET_SIZE) -> packet_size;
  1212. dec_opt(?INET_LOPT_READ_PACKETS) -> read_packets;
  1213. dec_opt(?INET_LOPT_NETNS) -> netns;
  1214. dec_opt(?INET_LOPT_TCP_SHOW_ECONNRESET) -> show_econnreset;
  1215. dec_opt(?INET_LOPT_LINE_DELIM) -> line_delimiter;
  1216. dec_opt(?INET_OPT_RAW) -> raw;
  1217. dec_opt(?INET_OPT_BIND_TO_DEVICE) -> bind_to_device;
  1218. dec_opt(I) when is_integer(I) -> undefined.
  1219. %% Metatypes:
  1220. %% [] Value must be 'undefined' or nonexistent
  1221. %% for setopts and getopts.
  1222. %% [Type] Value required for setopts and getopts,
  1223. %% will be encoded for both.
  1224. %% [Type,Default] Default used if value is 'undefined'.
  1225. %% [[Type,Default]] A combination of the two above.
  1226. %% Type Value must be 'undefined' or nonexistent for getops,
  1227. %% required for setopts.
  1228. %%
  1229. %% The use of [] and [[Type,Default]] is commented out in enc_value/2
  1230. %% and type_value/2 below since they are only used in record fields.
  1231. %% And record fields does not call enc_value/2 nor type_value/2.
  1232. %% Anyone introducing these metatypes otherwhere will have to activate
  1233. %% those clauses in enc_value/2 and type_value/2. You have been warned!
  1234. type_opt(get, raw) -> [{[int],[int],[binary_or_uint]}];
  1235. type_opt(_, raw) -> {int,int,binary};
  1236. %% NB: "sctp_status" and "sctp_get_peer_addr_info" are read-only options,
  1237. %% so they should not be NOT encoded for use with "setopt".
  1238. type_opt(get, sctp_status) ->
  1239. [{record,#sctp_status{
  1240. assoc_id = [sctp_assoc_id],
  1241. _ = []}}];
  1242. type_opt(get, sctp_get_peer_addr_info) ->
  1243. [{record,#sctp_paddrinfo{
  1244. assoc_id = [[sctp_assoc_id,0]],
  1245. address = [[addr,{any,0}]],
  1246. _ = []}}];
  1247. type_opt(_, Opt) ->
  1248. type_opt_1(Opt).
  1249. %% Types of option values, by option name:
  1250. %%
  1251. type_opt_1(reuseaddr) -> bool;
  1252. type_opt_1(keepalive) -> bool;
  1253. type_opt_1(dontroute) -> bool;
  1254. type_opt_1(linger) -> {bool,int};
  1255. type_opt_1(broadcast) -> bool;
  1256. type_opt_1(sndbuf) -> int;
  1257. type_opt_1(recbuf) -> int;
  1258. type_opt_1(priority) -> int;
  1259. type_opt_1(tos) -> int;
  1260. type_opt_1(tclass) -> int;
  1261. type_opt_1(nodelay) -> bool;
  1262. type_opt_1(ipv6_v6only) -> bool;
  1263. %% multicast
  1264. type_opt_1(multicast_ttl) -> int;
  1265. type_opt_1(multicast_loop) -> bool;
  1266. type_opt_1(multicast_if) -> ip;
  1267. type_opt_1(add_membership) -> {ip,ip};
  1268. type_opt_1(drop_membership) -> {ip,ip};
  1269. %% driver options
  1270. type_opt_1(header) -> uint;
  1271. type_opt_1(buffer) -> int;
  1272. type_opt_1(active) ->
  1273. {enum,[{false, ?INET_PASSIVE},
  1274. {true, ?INET_ACTIVE},
  1275. {once, ?INET_ONCE},
  1276. {multi, ?INET_MULTI}]};
  1277. type_opt_1(packet) ->
  1278. {enum,[{0, ?TCP_PB_RAW},
  1279. {1, ?TCP_PB_1},
  1280. {2, ?TCP_PB_2},
  1281. {4, ?TCP_PB_4},
  1282. {raw,?TCP_PB_RAW},
  1283. {sunrm, ?TCP_PB_RM},
  1284. {asn1, ?TCP_PB_ASN1},
  1285. {cdr, ?TCP_PB_CDR},
  1286. {fcgi, ?TCP_PB_FCGI},
  1287. {line, ?TCP_PB_LINE_LF},
  1288. {tpkt, ?TCP_PB_TPKT},
  1289. {http, ?TCP_PB_HTTP},
  1290. {httph,?TCP_PB_HTTPH},
  1291. {http_bin, ?TCP_PB_HTTP_BIN},
  1292. {httph_bin,?TCP_PB_HTTPH_BIN},
  1293. {ssl, ?TCP_PB_SSL_TLS}, % obsolete
  1294. {ssl_tls, ?TCP_PB_SSL_TLS}]};
  1295. type_opt_1(line_delimiter) -> int;
  1296. type_opt_1(mode) ->
  1297. {enum,[{list, ?INET_MODE_LIST},
  1298. {binary, ?INET_MODE_BINARY}]};
  1299. type_opt_1(deliver) ->
  1300. {enum,[{port, ?INET_DELIVER_PORT},
  1301. {term, ?INET_DELIVER_TERM}]};
  1302. type_opt_1(exit_on_close) -> bool;
  1303. type_opt_1(low_watermark) -> int;
  1304. type_opt_1(high_watermark) -> int;
  1305. type_opt_1(low_msgq_watermark) -> int;
  1306. type_opt_1(high_msgq_watermark) -> int;
  1307. type_opt_1(send_timeout) -> time;
  1308. type_opt_1(send_timeout_close) -> bool;
  1309. type_opt_1(delay_send) -> bool;
  1310. type_opt_1(packet_size) -> uint;
  1311. type_opt_1(read_packets) -> uint;
  1312. type_opt_1(netns) -> binary;
  1313. type_opt_1(show_econnreset) -> bool;
  1314. type_opt_1(bind_to_device) -> binary;
  1315. %%
  1316. %% SCTP options (to be set). If the type is a record type, the corresponding
  1317. %% record signature is returned, otherwise, an "elementary" type tag
  1318. %% is returned:
  1319. %%
  1320. %% for SCTP_OPT_RTOINFO
  1321. type_opt_1(sctp_rtoinfo) ->
  1322. [{record,#sctp_rtoinfo{
  1323. assoc_id = [[sctp_assoc_id,0]],
  1324. initial = [uint32,0],
  1325. max = [uint32,0],
  1326. min = [uint32,0]}}];
  1327. %% for SCTP_OPT_ASSOCINFO
  1328. type_opt_1(sctp_associnfo) ->
  1329. [{record,#sctp_assocparams{
  1330. assoc_id = [[sctp_assoc_id,0]],
  1331. asocmaxrxt = [uint16,0],
  1332. number_peer_destinations = [uint16,0],
  1333. peer_rwnd = [uint32,0],
  1334. local_rwnd = [uint32,0],
  1335. cookie_life = [uint32,0]}}];
  1336. %% for SCTP_OPT_INITMSG and SCTP_TAG_SEND_ANC_INITMSG (send*)
  1337. type_opt_1(sctp_initmsg) ->
  1338. [{record,#sctp_initmsg{
  1339. num_ostreams = [uint16,0],
  1340. max_instreams = [uint16,0],
  1341. max_attempts = [uint16,0],
  1342. max_init_timeo = [uint16,0]}}];
  1343. %%
  1344. type_opt_1(sctp_nodelay) -> bool;
  1345. type_opt_1(sctp_autoclose) -> uint;
  1346. type_opt_1(sctp_disable_fragments) -> bool;
  1347. type_opt_1(sctp_i_want_mapped_v4_addr) -> bool;
  1348. type_opt_1(sctp_maxseg) -> uint;
  1349. %% for SCTP_OPT_PRIMARY_ADDR
  1350. type_opt_1(sctp_primary_addr) ->
  1351. [{record,#sctp_prim{
  1352. assoc_id = [sctp_assoc_id],
  1353. addr = addr}}];
  1354. %% for SCTP_OPT_SET_PEER_PRIMARY_ADDR
  1355. type_opt_1(sctp_set_peer_primary_addr) ->
  1356. [{record,#sctp_setpeerprim{
  1357. assoc_id = [sctp_assoc_id],
  1358. addr = addr}}];
  1359. %% for SCTP_OPT_ADAPTATION_LAYER
  1360. type_opt_1(sctp_adaptation_layer) ->
  1361. [{record,#sctp_setadaptation{
  1362. adaptation_ind = [uint32,0]}}];
  1363. %% for SCTP_OPT_PEER_ADDR_PARAMS
  1364. type_opt_1(sctp_peer_addr_params) ->
  1365. [{record,#sctp_paddrparams{
  1366. assoc_id = [[sctp_assoc_id,0]],
  1367. address = [[addr,{any,0}]],
  1368. hbinterval = [uint32,0],
  1369. pathmaxrxt = [uint16,0],
  1370. pathmtu = [uint32,0],
  1371. sackdelay = [uint32,0],
  1372. flags =
  1373. [{bitenumlist,
  1374. [{hb_enable, ?SCTP_FLAG_HB_ENABLE},
  1375. {hb_disable, ?SCTP_FLAG_HB_DISABLE},
  1376. {hb_demand, ?SCTP_FLAG_HB_DEMAND},
  1377. {pmtud_enable, ?SCTP_FLAG_PMTUD_ENABLE},
  1378. {pmtud_disable, ?SCTP_FLAG_PMTUD_DISABLE},
  1379. {sackdelay_enable, ?SCTP_FLAG_SACKDELAY_ENABLE},
  1380. {sackdelay_disable, ?SCTP_FLAG_SACKDELAY_DISABLE}],
  1381. uint32},[]]}}];
  1382. %% for SCTP_OPT_DEFAULT_SEND_PARAM and SCTP_TAG_SEND_ANC_PARAMS (on send*)
  1383. type_opt_1(sctp_default_send_param) ->
  1384. [{record,#sctp_sndrcvinfo{
  1385. stream = [uint16,0],
  1386. ssn = [],
  1387. flags =
  1388. [{bitenumlist,
  1389. [{unordered, ?SCTP_FLAG_UNORDERED},
  1390. {addr_over, ?SCTP_FLAG_ADDR_OVER},
  1391. {abort, ?SCTP_FLAG_ABORT},
  1392. {eof, ?SCTP_FLAG_EOF}],
  1393. uint16},[]],
  1394. ppid = [uint32,0],
  1395. context = [uint32,0],
  1396. timetolive = [uint32,0],
  1397. tsn = [],
  1398. cumtsn = [],
  1399. assoc_id = [[sctp_assoc_id,0]]}}];
  1400. %% for SCTP_OPT_EVENTS
  1401. type_opt_1(sctp_events) ->
  1402. [{record,#sctp_event_subscribe{
  1403. data_io_event = [bool8,true],
  1404. association_event = [bool8,true],
  1405. address_event = [bool8,true],
  1406. send_failure_event = [bool8,true],
  1407. peer_error_event = [bool8,true],
  1408. shutdown_event = [bool8,true],
  1409. partial_delivery_event = [bool8,true],
  1410. adaptation_layer_event = [bool8,false],
  1411. authentication_event = [bool8,false]}}];
  1412. %% for SCTP_OPT_DELAYED_ACK_TIME
  1413. type_opt_1(sctp_delayed_ack_time) ->
  1414. [{record,#sctp_assoc_value{
  1415. assoc_id = [[sctp_assoc_id,0]],
  1416. assoc_value = [uint32,0]}}];
  1417. %%
  1418. type_opt_1(undefined) -> undefined;
  1419. type_opt_1(O) when is_atom(O) -> undefined.
  1420. %% Get. No supplied value.
  1421. type_value(get, undefined) -> false; % Undefined type
  1422. %% These two clauses can not happen since they are only used
  1423. %% in record fields - from record fields they must have a
  1424. %% value though it might be 'undefined', so record fields
  1425. %% calls type_value/3, not type_value/2.
  1426. %% type_value(get, []) -> true; % Ignored
  1427. %% type_value(get, [[Type,Default]]) -> % Required field, default value
  1428. %% type_value(get, Type, Default);
  1429. type_value(get, [{record,Types}]) -> % Implied default value for record
  1430. type_value_record(get, Types,
  1431. erlang:make_tuple(tuple_size(Types), undefined), 2);
  1432. type_value(get, [_]) -> false; % Required value missing
  1433. type_value(get, _) -> true. % Field is supposed to be undefined
  1434. %% Get and set. Value supplied.
  1435. type_value(_, undefined, _) -> false; % Undefined type
  1436. type_value(_, [], undefined) -> true; % Ignored
  1437. type_value(_, [], _) -> false; % Value should not be supplied
  1438. type_value(Q, [Type], Value) -> % Required field, proceed
  1439. type_value_default(Q, Type, Value);
  1440. type_value(set, Type, Value) -> % Required for setopts
  1441. type_value

Large files files are truncated, but you can click here to view the full file