inet:fdopen/2 fix for supporting externally open fd's of AF_LOCAL address family
Serge Aleynikov <[email protected]> Thu, 29 Jan 2015 21:03:01 -0500
| Newsgroups | gmane.comp.lang.erlang.patches |
|---|---|
| Message-ID | <CANt451nPq7RoR4CQRVu4qwuzYDPcA_4i+snQ7-ZJCK0EYSOHAw@mail.gmail.com> |
--===============8780832223456816713==
Content-Type: multipart/alternative; boundary=047d7bae438459407d050dd50208
--047d7bae438459407d050dd50208
Content-Type: text/plain; charset=UTF-8
When a AF_LOCAL (a.k.a. AF_UNIX) file descriptor is created externally
(e.g. Unix Domain Socket) and passed to `gen_tcp:listen(0, [{fd, FD}])`, the
present implementation incorrectly assigns the address family to be equal
to `inet`, which in the inet_drv driver translats to AF_INET instead
of AF_LOCAL (or AF_UNIX), and an `einval` error code is returned.
This patch fixes this problem such that the file descriptors of the
`local` address family are properly supported when such a file descriptor
is passed to the inet:fdopen/5, gen_tcp:connect/3, gen_tcp:listen/2,
gen_udp:open/2
calls via {fd, FD::integer()} option.
In order to connect a socket to a Unix Domain file descriptor use the
following options:
1> FD = ... % Open the AF_LOCAL *server* file descriptor
2> {ok, Sock} = gen_tcp:listen(0, [local, {fd,FD} | OtherOptions]).
% Now use the socket using gen_tcp module:
3> gen_tcp:send(Sock, <<"abc">>).
FD = ... % Open the AF_LOCAL *client* file descriptor
2> {ok, Sock} = gen_tcp:connect(0, [local, {fd,FD} | OtherOptions]).
% Now use the socket using gen_tcp module:
3> inet:setopts(S, [{active, once}]),
4> receive Msg -> Msg end.
{tcp,#Port<0.1195>,"abc"}
5> inet:setopts(S, [{active, false}]).
6> gen_tcp:recv(S,0,1000).
{ok,"efg"}
Note that in case of UDP client in order to preserve the active socket
signature {udp, ErlPort, Addr, Port, Data} and passive socket's
gen_udp:recv3 return signature ({ok, {Address, Port, Packet}}), the Address
on local socket family is a string containing the underlying socket's
filename, and Port=0. E.g.:
{ok, {"/tmp/test.sock", 0, <<"some data">>}} = gen_udp:recv(S, 0, 1000).
git fetch https://github.com/saleyn/otp uds
https://github.com/saleyn/otp/compare/erlang:maint...uds
https://github.com/saleyn/otp/compare/erlang:maint...uds.patch
A sample project using this patch can be found here:
https://github.com/saleyn/euds. It uses a NIF library to create and FD of
AF_LOCAL family, and passes it to either gen_tcp or gen_udp for further
handling.
Regards,
Serge
--047d7bae438459407d050dd50208
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_default"><font face=3D"arial, helvetic=
a, sans-serif"><div class=3D"gmail_default">When a AF_LOCAL (a.k.a. AF_UNIX=
) file descriptor is created externally</div></font><font face=3D"arial, he=
lvetica, sans-serif"><div class=3D"gmail_default">(e.g. Unix Domain Socket)=
and passed to `gen_tcp:listen(0, [{fd, FD}])`, the</div><div class=3D"gmai=
l_default">present implementation incorrectly assigns the address family to=
be equal</div><div class=3D"gmail_default">to `inet`, which in the inet_dr=
v driver translats to AF_INET instead</div><div class=3D"gmail_default">of =
AF_LOCAL (or AF_UNIX), and an `einval` error code is returned.</div><div cl=
ass=3D"gmail_default"><br></div><div class=3D"gmail_default">This patch fix=
es this problem such that the file descriptors of the</div><div class=3D"gm=
ail_default">`local` address family are properly supported when such a file=
descriptor</div><div class=3D"gmail_default">is passed to the inet:fdopen/=
5, gen_tcp:connect/3, gen_tcp:listen/2, gen_udp:open/2</div><div class=3D"g=
mail_default">calls via {fd, FD::integer()} option.</div><div class=3D"gmai=
l_default"><br></div><div class=3D"gmail_default">In order to connect a soc=
ket to a Unix Domain file descriptor use the following options:</div><div c=
lass=3D"gmail_default"><br></div><div class=3D"gmail_default"><div class=3D=
"gmail_default">=C2=A0 =C2=A0 1> FD =3D ... % Open the AF_LOCAL *server*=
file descriptor</div><div class=3D"gmail_default">=C2=A0 =C2=A0 2> {ok,=
Sock} =3D gen_tcp:listen(0, [local, {fd,FD} | OtherOptions]).</div><div cl=
ass=3D"gmail_default">=C2=A0 =C2=A0 % Now use the socket using gen_tcp modu=
le:<br></div><div class=3D"gmail_default">=C2=A0 =C2=A0 3> gen_tcp:send(=
Sock, <<"abc">>).</div><div><br></div><div>=C2=A0 =C2=
=A0 FD =3D ... % Open the AF_LOCAL *client* file descriptor<br></div></div>=
<div class=3D"gmail_default">=C2=A0 =C2=A0 2> {ok, Sock} =3D gen_tcp:con=
nect(0, [local, {fd,FD} | OtherOptions]).</div><div class=3D"gmail_default"=
>=C2=A0 =C2=A0 % Now use the socket using gen_tcp module:<br></div><div cla=
ss=3D"gmail_default">=C2=A0 =C2=A0 3> inet:setopts(S, [{active, once}]),=
<br></div></font><font face=3D"arial, helvetica, sans-serif"><div class=3D"=
gmail_default">=C2=A0 =C2=A0 4> receive Msg -> Msg end.</div><div cla=
ss=3D"gmail_default">=C2=A0 =C2=A0=C2=A0{tcp,#Port<0.1195>,"abc&=
quot;}</div><div class=3D"gmail_default">=C2=A0 =C2=A0 5>=C2=A0inet:seto=
pts(S, [{active, false}]).</div><div class=3D"gmail_default">=C2=A0 =C2=A0 =
6>=C2=A0gen_tcp:recv(S,0,1000).</div><div class=3D"gmail_default">=C2=A0=
=C2=A0=C2=A0{ok,"efg"}</div><div class=3D"gmail_default"><br></d=
iv><div class=3D"gmail_default">Note that in case of UDP client in order to=
preserve the active socket signature {udp, ErlPort, Addr, Port, Data} and =
passive socket's gen_udp:recv3 return signature ({ok, {Address, Port, P=
acket}}), the Address on local socket family is a string containing the und=
erlying socket's filename, and Port=3D0. E.g.:</div><div class=3D"gmail=
_default"><br></div><div class=3D"gmail_default">=C2=A0 =C2=A0 {ok, {"=
/tmp/test.sock", 0, <<"some data">>}} =3D gen_ud=
p:recv(S, 0, 1000).</div></font><font face=3D"arial, helvetica, sans-serif"=
><div class=3D"gmail_default"><br></div></font></div><div class=3D"gmail_de=
fault"><font face=3D"arial, helvetica, sans-serif">git fetch=C2=A0</font><s=
pan style=3D"font-family:arial,helvetica,sans-serif"><a href=3D"https://git=
hub.com/saleyn/otp" target=3D"_blank">https://github.com/saleyn/otp</a> uds=
</span></div><div class=3D"gmail_default"><span style=3D"font-family:arial,=
helvetica,sans-serif"><br></span></div><div class=3D"gmail_default"><font f=
ace=3D"arial, helvetica, sans-serif"><a href=3D"https://github.com/saleyn/o=
tp/compare/erlang:maint...uds" target=3D"_blank">https://github.com/saleyn/=
otp/compare/erlang:maint...uds</a></font><br></div><div class=3D"gmail_defa=
ult"><font face=3D"arial, helvetica, sans-serif"><a href=3D"https://github.=
com/saleyn/otp/compare/erlang:maint...uds.patch" target=3D"_blank">https://=
github.com/saleyn/otp/compare/erlang:maint...uds.patch</a><br></font></div>=
<div class=3D"gmail_default"><font face=3D"arial, helvetica, sans-serif"><b=
r></font></div><div class=3D"gmail_default"><font face=3D"arial, helvetica,=
sans-serif">A sample project using this patch can be found here:=C2=A0</fo=
nt><a href=3D"https://github.com/saleyn/euds" target=3D"_blank" style=3D"fo=
nt-family:arial,helvetica,sans-serif">https://github.com/saleyn/euds</a>. I=
t uses a NIF library to create and FD of AF_LOCAL family, and passes it to =
either gen_tcp or gen_udp for further handling.</div><div class=3D"gmail_de=
fault"><br></div><div class=3D"gmail_default">Regards,</div><div class=3D"g=
mail_default"><br></div><div class=3D"gmail_default">Serge</div><div class=
=3D"gmail_default"><font face=3D"arial, helvetica, sans-serif"><br></font><=
/div><div class=3D"gmail_default"><font face=3D"arial, helvetica, sans-seri=
f"><br></font></div></div>
--047d7bae438459407d050dd50208--
--===============8780832223456816713==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
erlang-patches mailing list
[email protected]
http://erlang.org/mailman/listinfo/erlang-patches
--===============8780832223456816713==--