Skip to content

Commit 30b010f

Browse files
AtlanticFlacatoire
andauthored
Add: socket_sendmsg function doc (#2039)
* Add: socket_sendmsg function doc * Use simpara for the inline-only para elements The DocBook Lint job requires simpara for para elements in the diff whose content is inline only. * Correct the message array structure and the flags table The message array read by socket_sendmsg() only has the keys name, iov and control, all of them optional; any other key is ignored. The flags key comes from the array returned by socket_recvmsg() and has no meaning when sending. control is a list of ancillary data messages, and it is each element that carries level, type and data, not control itself. name depends on the address family: addr and port for AF_INET, additionally flowinfo and scope_id for AF_INET6, and path for AF_UNIX, with an optional family key selecting the family explicitly. Also restore the MSG_EOR wording used by socket_send() and socket_sendto(), add the MSG_EOF row those two pages carry, and keep the original refpurpose. * Add examples for socket_sendmsg() The structure of the message array is the only hard part of this function, so the page needs to show it. The first example sends a datagram using name and iov, the second passes a file descriptor through the control key with SCM_RIGHTS, which is the reason to reach for socket_sendmsg() over socket_sendto(). * Fix inaccuracies in the socket_sendmsg() page Drop the MSG_EOF row: its description is the BSD semantics, and on Linux the constant is an alias of MSG_FIN which the kernel ignores for TCP, so the flag neither closes the sender side nor ends the transaction there. List the supported level and type pairs for control instead of leaving the shape of data unspecified, since the set is small and a pair outside it fails. Also: name the missing flags element, which only exists in the array filled in by socket_recvmsg(); state that addr accepts a host name and that family must match the socket; say that an empty iov sends no data rather than an empty message, which only holds for datagram sockets; add socket_create_pair() to the socket description, as the second example uses it; and note that the file descriptor example does not run on Windows. --------- Co-authored-by: Louis-Arnaud <la.catoire@gmail.com>
1 parent 3505aae commit 30b010f

1 file changed

Lines changed: 216 additions & 7 deletions

File tree

reference/sockets/functions/socket-sendmsg.xml

Lines changed: 216 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
<methodparam><type>array</type><parameter>message</parameter></methodparam>
1414
<methodparam choice="opt"><type>int</type><parameter>flags</parameter><initializer>0</initializer></methodparam>
1515
</methodsynopsis>
16-
<para>
17-
</para>
18-
&warn.undocumented.func;
16+
<simpara>
17+
The function <function>socket_sendmsg</function> sends the message described by
18+
<parameter>message</parameter> through the socket <parameter>socket</parameter>,
19+
using the <literal>sendmsg()</literal> system call.
20+
</simpara>
1921
</refsect1>
2022

2123
<refsect1 role="parameters">
@@ -25,21 +27,154 @@
2527
<varlistentry>
2628
<term><parameter>socket</parameter></term>
2729
<listitem>
28-
<para>
29-
</para>
30+
<simpara>
31+
A <classname>Socket</classname> instance created with <function>socket_create</function>,
32+
<function>socket_accept</function> or <function>socket_create_pair</function>.
33+
</simpara>
3034
</listitem>
3135
</varlistentry>
3236
<varlistentry>
3337
<term><parameter>message</parameter></term>
3438
<listitem>
35-
<para>
36-
</para>
39+
<simpara>
40+
An associative array which may contain the following elements. All of them
41+
are optional, and unrecognized keys are silently ignored. In particular
42+
there is no <varname>flags</varname> element when sending; that key only
43+
appears in the array filled in by <function>socket_recvmsg</function>.
44+
</simpara>
45+
<variablelist>
46+
<varlistentry>
47+
<term><varname>name</varname></term>
48+
<listitem>
49+
<simpara>
50+
The address of the remote host, as an array. Its keys are
51+
<varname>addr</varname> and <varname>port</varname> for
52+
<constant>AF_INET</constant>; <varname>addr</varname>,
53+
<varname>port</varname>, <varname>flowinfo</varname> and
54+
<varname>scope_id</varname> for <constant>AF_INET6</constant>; and
55+
<varname>path</varname> for <constant>AF_UNIX</constant>.
56+
<varname>addr</varname> accepts an IP address or a host name, which is
57+
then resolved. An optional <varname>family</varname> key selects the
58+
address family explicitly; if omitted, the family of
59+
<parameter>socket</parameter> is used. A family the socket does not
60+
support makes the call fail.
61+
</simpara>
62+
</listitem>
63+
</varlistentry>
64+
<varlistentry>
65+
<term><varname>iov</varname></term>
66+
<listitem>
67+
<simpara>
68+
A list of buffers holding the data to send, which are sent in order as a
69+
single message. Array keys are ignored and the values are converted to
70+
string. When this key is missing or empty, no data is sent and the
71+
function returns <literal>0</literal>.
72+
</simpara>
73+
</listitem>
74+
</varlistentry>
75+
<varlistentry>
76+
<term><varname>control</varname></term>
77+
<listitem>
78+
<simpara>
79+
A list of ancillary data messages. Each is an array with the keys
80+
<varname>level</varname>, <varname>type</varname> and
81+
<varname>data</varname>. Only the pairs below are supported, and their
82+
availability depends on the platform.
83+
</simpara>
84+
<table>
85+
<title>Supported ancillary data</title>
86+
<tgroup cols="3">
87+
<thead>
88+
<row>
89+
<entry><varname>level</varname></entry>
90+
<entry><varname>type</varname></entry>
91+
<entry><varname>data</varname></entry>
92+
</row>
93+
</thead>
94+
<tbody>
95+
<row>
96+
<entry><constant>SOL_SOCKET</constant></entry>
97+
<entry><constant>SCM_RIGHTS</constant></entry>
98+
<entry>
99+
A non-empty list of <classname>Socket</classname> instances or
100+
stream resources, whose file descriptors are sent to the receiving
101+
process.
102+
</entry>
103+
</row>
104+
<row>
105+
<entry><constant>SOL_SOCKET</constant></entry>
106+
<entry><constant>SCM_CREDENTIALS</constant></entry>
107+
<entry>
108+
An array with the keys <varname>pid</varname>,
109+
<varname>uid</varname> and <varname>gid</varname>. Named
110+
<constant>SCM_CREDS</constant> or <constant>SCM_CREDS2</constant>
111+
on some systems.
112+
</entry>
113+
</row>
114+
<row>
115+
<entry><constant>IPPROTO_IPV6</constant></entry>
116+
<entry><constant>IPV6_PKTINFO</constant></entry>
117+
<entry>
118+
An array with the keys <varname>addr</varname> and
119+
<varname>ifindex</varname>.
120+
</entry>
121+
</row>
122+
<row>
123+
<entry><constant>IPPROTO_IPV6</constant></entry>
124+
<entry><constant>IPV6_HOPLIMIT</constant></entry>
125+
<entry>An <type>int</type>.</entry>
126+
</row>
127+
<row>
128+
<entry><constant>IPPROTO_IPV6</constant></entry>
129+
<entry><constant>IPV6_TCLASS</constant></entry>
130+
<entry>An <type>int</type>.</entry>
131+
</row>
132+
</tbody>
133+
</tgroup>
134+
</table>
135+
</listitem>
136+
</varlistentry>
137+
</variablelist>
37138
</listitem>
38139
</varlistentry>
39140
<varlistentry>
40141
<term><parameter>flags</parameter></term>
41142
<listitem>
42143
<para>
144+
The value of <parameter>flags</parameter> can be any combination of the
145+
following flags, joined with the binary OR (<literal>|</literal>) operator.
146+
<table>
147+
<title>Possible values for <parameter>flags</parameter></title>
148+
<tgroup cols="2">
149+
<tbody>
150+
<row>
151+
<entry><constant>MSG_OOB</constant></entry>
152+
<entry>
153+
Send OOB (out-of-band) data.
154+
</entry>
155+
</row>
156+
<row>
157+
<entry><constant>MSG_EOR</constant></entry>
158+
<entry>
159+
Indicate a record mark. The sent data completes the record.
160+
</entry>
161+
</row>
162+
<row>
163+
<entry><constant>MSG_DONTWAIT</constant></entry>
164+
<entry>
165+
With this flag set, the function returns even if it would normally
166+
have blocked.
167+
</entry>
168+
</row>
169+
<row>
170+
<entry><constant>MSG_DONTROUTE</constant></entry>
171+
<entry>
172+
Bypass routing, use direct interface.
173+
</entry>
174+
</row>
175+
</tbody>
176+
</tgroup>
177+
</table>
43178
</para>
44179
</listitem>
45180
</varlistentry>
@@ -71,6 +206,80 @@
71206
</informaltable>
72207
</refsect1>
73208

209+
<refsect1 role="examples">
210+
&reftitle.examples;
211+
<example>
212+
<title>Sending a message with <function>socket_sendmsg</function></title>
213+
<programlisting role="php">
214+
<![CDATA[
215+
<?php
216+
$server = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
217+
socket_bind($server, '127.0.0.1', 1053);
218+
219+
$client = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
220+
$sent = socket_sendmsg($client, [
221+
'name' => ['addr' => '127.0.0.1', 'port' => 1053],
222+
'iov' => ['Hello ', 'world'],
223+
], 0);
224+
225+
echo "sent: $sent\n";
226+
227+
socket_recvfrom($server, $buffer, 64, 0, $from, $port);
228+
echo "received: $buffer\n";
229+
?>
230+
]]>
231+
</programlisting>
232+
&example.outputs;
233+
<screen>
234+
<![CDATA[
235+
sent: 11
236+
received: Hello world
237+
]]>
238+
</screen>
239+
</example>
240+
<example>
241+
<title>Passing a file descriptor over a UNIX socket</title>
242+
<simpara>
243+
The <varname>control</varname> key carries ancillary data. With
244+
<constant>SCM_RIGHTS</constant>, it transfers open file descriptors to the
245+
process at the other end of a UNIX socket. This is not available on Windows.
246+
</simpara>
247+
<programlisting role="php">
248+
<![CDATA[
249+
<?php
250+
socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $pair);
251+
[$sender, $receiver] = $pair;
252+
253+
$file = fopen(__FILE__, 'r');
254+
255+
socket_sendmsg($sender, [
256+
// At least one byte of regular data must accompany the ancillary data.
257+
'iov' => ['fd'],
258+
'control' => [
259+
['level' => SOL_SOCKET, 'type' => SCM_RIGHTS, 'data' => [$file]],
260+
],
261+
], 0);
262+
263+
$message = [
264+
'buffer_size' => 16,
265+
'controllen' => socket_cmsg_space(SOL_SOCKET, SCM_RIGHTS, 1),
266+
];
267+
socket_recvmsg($receiver, $message, 0);
268+
269+
$received = $message['control'][0]['data'][0];
270+
echo "first line: ", fgets($received);
271+
?>
272+
]]>
273+
</programlisting>
274+
&example.outputs;
275+
<screen>
276+
<![CDATA[
277+
first line: <?php
278+
]]>
279+
</screen>
280+
</example>
281+
</refsect1>
282+
74283
<refsect1 role="seealso">
75284
&reftitle.seealso;
76285
<para>

0 commit comments

Comments
 (0)