PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/kernel/src/gen_udp.erl

http://github.com/erlang/otp
Erlang | 286 lines | 233 code | 22 blank | 31 comment | 0 complexity | 07f339c03db8d6a2757c19e73ef279d7 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, Unlicense, LGPL-2.1, MPL-2.0-no-copyleft-exception
  1. %%
  2. %% %CopyrightBegin%
  3. %%
  4. %% Copyright Ericsson AB 1997-2020. 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. -module(gen_udp).
  21. -export([open/1, open/2, close/1]).
  22. -export([send/2, send/3, send/4, send/5, recv/2, recv/3, connect/3]).
  23. -export([controlling_process/2]).
  24. -export([fdopen/2]).
  25. -include("inet_int.hrl").
  26. -type option() ::
  27. {active, true | false | once | -32768..32767} |
  28. {add_membership, {inet:ip_address(), inet:ip_address()}} |
  29. {broadcast, boolean()} |
  30. {buffer, non_neg_integer()} |
  31. {deliver, port | term} |
  32. {dontroute, boolean()} |
  33. {drop_membership, {inet:ip_address(), inet:ip_address()}} |
  34. {header, non_neg_integer()} |
  35. {high_msgq_watermark, pos_integer()} |
  36. {low_msgq_watermark, pos_integer()} |
  37. {mode, list | binary} | list | binary |
  38. {multicast_if, inet:ip_address()} |
  39. {multicast_loop, boolean()} |
  40. {multicast_ttl, non_neg_integer()} |
  41. {priority, non_neg_integer()} |
  42. {raw,
  43. Protocol :: non_neg_integer(),
  44. OptionNum :: non_neg_integer(),
  45. ValueBin :: binary()} |
  46. {read_packets, non_neg_integer()} |
  47. {recbuf, non_neg_integer()} |
  48. {reuseaddr, boolean()} |
  49. {sndbuf, non_neg_integer()} |
  50. {tos, non_neg_integer()} |
  51. {tclass, non_neg_integer()} |
  52. {ttl, non_neg_integer()} |
  53. {recvtos, boolean()} |
  54. {recvtclass, boolean()} |
  55. {recvttl, boolean()} |
  56. {ipv6_v6only, boolean()}.
  57. -type option_name() ::
  58. active |
  59. broadcast |
  60. buffer |
  61. deliver |
  62. dontroute |
  63. header |
  64. high_msgq_watermark |
  65. low_msgq_watermark |
  66. mode |
  67. multicast_if |
  68. multicast_loop |
  69. multicast_ttl |
  70. priority |
  71. {raw,
  72. Protocol :: non_neg_integer(),
  73. OptionNum :: non_neg_integer(),
  74. ValueSpec :: (ValueSize :: non_neg_integer()) |
  75. (ValueBin :: binary())} |
  76. read_packets |
  77. recbuf |
  78. reuseaddr |
  79. sndbuf |
  80. tos |
  81. tclass |
  82. ttl |
  83. recvtos |
  84. recvtclass |
  85. recvttl |
  86. pktoptions |
  87. ipv6_v6only.
  88. -type socket() :: port().
  89. -export_type([option/0, option_name/0, socket/0]).
  90. -spec open(Port) -> {ok, Socket} | {error, Reason} when
  91. Port :: inet:port_number(),
  92. Socket :: socket(),
  93. Reason :: system_limit | inet:posix().
  94. open(Port) ->
  95. open(Port, []).
  96. -spec open(Port, Opts) -> {ok, Socket} | {error, Reason} when
  97. Port :: inet:port_number(),
  98. Opts :: [Option],
  99. Option :: {ip, inet:socket_address()}
  100. | {fd, non_neg_integer()}
  101. | {ifaddr, inet:socket_address()}
  102. | inet:address_family()
  103. | {port, inet:port_number()}
  104. | {netns, file:filename_all()}
  105. | {bind_to_device, binary()}
  106. | option(),
  107. Socket :: socket(),
  108. Reason :: system_limit | inet:posix().
  109. open(Port, Opts0) ->
  110. {Mod, Opts} = inet:udp_module(Opts0),
  111. {ok, UP} = Mod:getserv(Port),
  112. Mod:open(UP, Opts).
  113. -spec close(Socket) -> ok when
  114. Socket :: socket().
  115. close(S) ->
  116. inet:udp_close(S).
  117. -spec send(Socket, Destination, Packet) -> ok | {error, Reason} when
  118. Socket :: socket(),
  119. Destination :: {inet:ip_address(), inet:port_number()} |
  120. inet:family_address(),
  121. Packet :: iodata(),
  122. Reason :: not_owner | inet:posix().
  123. %%%
  124. send(Socket, Destination, Packet) ->
  125. send(Socket, Destination, [], Packet).
  126. -spec send(Socket, Host, Port, Packet) -> ok | {error, Reason} when
  127. Socket :: socket(),
  128. Host :: inet:hostname() | inet:ip_address(),
  129. Port :: inet:port_number() | atom(),
  130. Packet :: iodata(),
  131. Reason :: not_owner | inet:posix();
  132. %%%
  133. (Socket, Destination, AncData, Packet) -> ok | {error, Reason} when
  134. Socket :: socket(),
  135. Destination :: {inet:ip_address(), inet:port_number()} |
  136. inet:family_address(),
  137. AncData :: inet:ancillary_data(),
  138. Packet :: iodata(),
  139. Reason :: not_owner | inet:posix();
  140. %%%
  141. (Socket, Destination, PortZero, Packet) -> ok | {error, Reason} when
  142. Socket :: socket(),
  143. Destination :: {inet:ip_address(), inet:port_number()} |
  144. inet:family_address(),
  145. PortZero :: inet:port_number(),
  146. Packet :: iodata(),
  147. Reason :: not_owner | inet:posix().
  148. %%%
  149. send(S, {_,_} = Destination, PortZero = AncData, Packet) when is_port(S) ->
  150. %% Destination is {Family,Addr} | {IP,Port},
  151. %% so it is complete - argument PortZero is redundant
  152. if
  153. PortZero =:= 0 ->
  154. case inet_db:lookup_socket(S) of
  155. {ok, Mod} ->
  156. Mod:send(S, Destination, [], Packet);
  157. Error ->
  158. Error
  159. end;
  160. is_integer(PortZero) ->
  161. %% Redundant PortZero; must be 0
  162. {error, einval};
  163. is_list(AncData) ->
  164. case inet_db:lookup_socket(S) of
  165. {ok, Mod} ->
  166. Mod:send(S, Destination, AncData, Packet);
  167. Error ->
  168. Error
  169. end
  170. end;
  171. send(S, Host, Port, Packet) when is_port(S) ->
  172. send(S, Host, Port, [], Packet).
  173. -spec send(Socket, Host, Port, AncData, Packet) -> ok | {error, Reason} when
  174. Socket :: socket(),
  175. Host :: inet:hostname() | inet:ip_address() | inet:local_address(),
  176. Port :: inet:port_number() | atom(),
  177. AncData :: inet:ancillary_data(),
  178. Packet :: iodata(),
  179. Reason :: not_owner | inet:posix().
  180. %%%
  181. send(S, Host, Port, AncData, Packet)
  182. when is_port(S), is_list(AncData) ->
  183. case inet_db:lookup_socket(S) of
  184. {ok, Mod} ->
  185. case Mod:getaddr(Host) of
  186. {ok,IP} ->
  187. case Mod:getserv(Port) of
  188. {ok,P} -> Mod:send(S, {IP,P}, AncData, Packet);
  189. {error,einval} -> exit(badarg);
  190. Error -> Error
  191. end;
  192. {error,einval} -> exit(badarg);
  193. Error -> Error
  194. end;
  195. Error ->
  196. Error
  197. end.
  198. %% Connected send
  199. send(S, Packet) when is_port(S) ->
  200. case inet_db:lookup_socket(S) of
  201. {ok, Mod} ->
  202. Mod:send(S, Packet);
  203. Error ->
  204. Error
  205. end.
  206. -spec recv(Socket, Length) ->
  207. {ok, RecvData} | {error, Reason} when
  208. Socket :: socket(),
  209. Length :: non_neg_integer(),
  210. RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
  211. Address :: inet:ip_address() | inet:returned_non_ip_address(),
  212. Port :: inet:port_number(),
  213. AncData :: inet:ancillary_data(),
  214. Packet :: string() | binary(),
  215. Reason :: not_owner | inet:posix().
  216. recv(S,Len) when is_port(S), is_integer(Len) ->
  217. case inet_db:lookup_socket(S) of
  218. {ok, Mod} ->
  219. Mod:recv(S, Len);
  220. Error ->
  221. Error
  222. end.
  223. -spec recv(Socket, Length, Timeout) ->
  224. {ok, RecvData} | {error, Reason} when
  225. Socket :: socket(),
  226. Length :: non_neg_integer(),
  227. Timeout :: timeout(),
  228. RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
  229. Address :: inet:ip_address() | inet:returned_non_ip_address(),
  230. Port :: inet:port_number(),
  231. AncData :: inet:ancillary_data(),
  232. Packet :: string() | binary(),
  233. Reason :: not_owner | timeout | inet:posix().
  234. recv(S,Len,Time) when is_port(S) ->
  235. case inet_db:lookup_socket(S) of
  236. {ok, Mod} ->
  237. Mod:recv(S, Len,Time);
  238. Error ->
  239. Error
  240. end.
  241. connect(S, Address, Port) when is_port(S) ->
  242. case inet_db:lookup_socket(S) of
  243. {ok, Mod} ->
  244. case Mod:getaddr(Address) of
  245. {ok, IP} ->
  246. Mod:connect(S, IP, Port);
  247. Error ->
  248. Error
  249. end;
  250. Error ->
  251. Error
  252. end.
  253. -spec controlling_process(Socket, Pid) -> ok | {error, Reason} when
  254. Socket :: socket(),
  255. Pid :: pid(),
  256. Reason :: closed | not_owner | badarg | inet:posix().
  257. controlling_process(S, NewOwner) ->
  258. inet:udp_controlling_process(S, NewOwner).
  259. %%
  260. %% Create a port/socket from a file descriptor
  261. %%
  262. fdopen(Fd, Opts0) ->
  263. {Mod,Opts} = inet:udp_module(Opts0),
  264. Mod:fdopen(Fd, Opts).