1e66f31c5Sopenharmony_ciNetworking
2e66f31c5Sopenharmony_ci==========
3e66f31c5Sopenharmony_ci
4e66f31c5Sopenharmony_ciNetworking in libuv is not much different from directly using the BSD socket
5e66f31c5Sopenharmony_ciinterface, some things are easier, all are non-blocking, but the concepts stay
6e66f31c5Sopenharmony_cithe same. In addition libuv offers utility functions to abstract the annoying,
7e66f31c5Sopenharmony_cirepetitive and low-level tasks like setting up sockets using the BSD socket
8e66f31c5Sopenharmony_cistructures, DNS lookup, and tweaking various socket parameters.
9e66f31c5Sopenharmony_ci
10e66f31c5Sopenharmony_ciThe ``uv_tcp_t`` and ``uv_udp_t`` structures are used for network I/O.
11e66f31c5Sopenharmony_ci
12e66f31c5Sopenharmony_ci.. NOTE::
13e66f31c5Sopenharmony_ci
14e66f31c5Sopenharmony_ci  The code samples in this chapter exist to show certain libuv APIs. They are
15e66f31c5Sopenharmony_ci  not examples of good quality code. They leak memory and don't always close
16e66f31c5Sopenharmony_ci  connections properly.
17e66f31c5Sopenharmony_ci
18e66f31c5Sopenharmony_ciTCP
19e66f31c5Sopenharmony_ci---
20e66f31c5Sopenharmony_ci
21e66f31c5Sopenharmony_ciTCP is a connection oriented, stream protocol and is therefore based on the
22e66f31c5Sopenharmony_cilibuv streams infrastructure.
23e66f31c5Sopenharmony_ci
24e66f31c5Sopenharmony_ciServer
25e66f31c5Sopenharmony_ci++++++
26e66f31c5Sopenharmony_ci
27e66f31c5Sopenharmony_ciServer sockets proceed by:
28e66f31c5Sopenharmony_ci
29e66f31c5Sopenharmony_ci1. ``uv_tcp_init`` the TCP handle.
30e66f31c5Sopenharmony_ci2. ``uv_tcp_bind`` it.
31e66f31c5Sopenharmony_ci3. Call ``uv_listen`` on the handle to have a callback invoked whenever a new
32e66f31c5Sopenharmony_ci   connection is established by a client.
33e66f31c5Sopenharmony_ci4. Use ``uv_accept`` to accept the connection.
34e66f31c5Sopenharmony_ci5. Use :ref:`stream operations <buffers-and-streams>` to communicate with the
35e66f31c5Sopenharmony_ci   client.
36e66f31c5Sopenharmony_ci
37e66f31c5Sopenharmony_ciHere is a simple echo server
38e66f31c5Sopenharmony_ci
39e66f31c5Sopenharmony_ci.. rubric:: tcp-echo-server/main.c - The listen socket
40e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/tcp-echo-server/main.c
41e66f31c5Sopenharmony_ci    :language: c
42e66f31c5Sopenharmony_ci    :linenos:
43e66f31c5Sopenharmony_ci    :lines: 68-
44e66f31c5Sopenharmony_ci    :emphasize-lines: 4-5,7-10
45e66f31c5Sopenharmony_ci
46e66f31c5Sopenharmony_ciYou can see the utility function ``uv_ip4_addr`` being used to convert from
47e66f31c5Sopenharmony_cia human readable IP address, port pair to the sockaddr_in structure required by
48e66f31c5Sopenharmony_cithe BSD socket APIs. The reverse can be obtained using ``uv_ip4_name``.
49e66f31c5Sopenharmony_ci
50e66f31c5Sopenharmony_ci.. NOTE::
51e66f31c5Sopenharmony_ci
52e66f31c5Sopenharmony_ci    There are ``uv_ip6_*`` analogues for the ip4 functions.
53e66f31c5Sopenharmony_ci
54e66f31c5Sopenharmony_ciMost of the setup functions are synchronous since they are CPU-bound.
55e66f31c5Sopenharmony_ci``uv_listen`` is where we return to libuv's callback style. The second
56e66f31c5Sopenharmony_ciarguments is the backlog queue -- the maximum length of queued connections.
57e66f31c5Sopenharmony_ci
58e66f31c5Sopenharmony_ciWhen a connection is initiated by clients, the callback is required to set up
59e66f31c5Sopenharmony_cia handle for the client socket and associate the handle using ``uv_accept``.
60e66f31c5Sopenharmony_ciIn this case we also establish interest in reading from this stream.
61e66f31c5Sopenharmony_ci
62e66f31c5Sopenharmony_ci.. rubric:: tcp-echo-server/main.c - Accepting the client
63e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/tcp-echo-server/main.c
64e66f31c5Sopenharmony_ci    :language: c
65e66f31c5Sopenharmony_ci    :linenos:
66e66f31c5Sopenharmony_ci    :lines: 51-66
67e66f31c5Sopenharmony_ci    :emphasize-lines: 9-10
68e66f31c5Sopenharmony_ci
69e66f31c5Sopenharmony_ciThe remaining set of functions is very similar to the streams example and can
70e66f31c5Sopenharmony_cibe found in the code. Just remember to call ``uv_close`` when the socket isn't
71e66f31c5Sopenharmony_cirequired. This can be done even in the ``uv_listen`` callback if you are not
72e66f31c5Sopenharmony_ciinterested in accepting the connection.
73e66f31c5Sopenharmony_ci
74e66f31c5Sopenharmony_ciClient
75e66f31c5Sopenharmony_ci++++++
76e66f31c5Sopenharmony_ci
77e66f31c5Sopenharmony_ciWhere you do bind/listen/accept on the server, on the client side it's simply
78e66f31c5Sopenharmony_cia matter of calling ``uv_tcp_connect``. The same ``uv_connect_cb`` style
79e66f31c5Sopenharmony_cicallback of ``uv_listen`` is used by ``uv_tcp_connect``. Try::
80e66f31c5Sopenharmony_ci
81e66f31c5Sopenharmony_ci    uv_tcp_t* socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
82e66f31c5Sopenharmony_ci    uv_tcp_init(loop, socket);
83e66f31c5Sopenharmony_ci
84e66f31c5Sopenharmony_ci    uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
85e66f31c5Sopenharmony_ci
86e66f31c5Sopenharmony_ci    struct sockaddr_in dest;
87e66f31c5Sopenharmony_ci    uv_ip4_addr("127.0.0.1", 80, &dest);
88e66f31c5Sopenharmony_ci
89e66f31c5Sopenharmony_ci    uv_tcp_connect(connect, socket, (const struct sockaddr*)&dest, on_connect);
90e66f31c5Sopenharmony_ci
91e66f31c5Sopenharmony_ciwhere ``on_connect`` will be called after the connection is established. The
92e66f31c5Sopenharmony_cicallback receives the ``uv_connect_t`` struct, which has a member ``.handle``
93e66f31c5Sopenharmony_cipointing to the socket.
94e66f31c5Sopenharmony_ci
95e66f31c5Sopenharmony_ciUDP
96e66f31c5Sopenharmony_ci---
97e66f31c5Sopenharmony_ci
98e66f31c5Sopenharmony_ciThe `User Datagram Protocol`_ offers connectionless, unreliable network
99e66f31c5Sopenharmony_cicommunication. Hence libuv doesn't offer a stream. Instead libuv provides
100e66f31c5Sopenharmony_cinon-blocking UDP support via the `uv_udp_t` handle (for receiving) and
101e66f31c5Sopenharmony_ci`uv_udp_send_t` request (for sending) and related functions. That said, the
102e66f31c5Sopenharmony_ciactual API for reading/writing is very similar to normal stream reads. To look
103e66f31c5Sopenharmony_ciat how UDP can be used, the example shows the first stage of obtaining an IP
104e66f31c5Sopenharmony_ciaddress from a `DHCP`_ server -- DHCP Discover.
105e66f31c5Sopenharmony_ci
106e66f31c5Sopenharmony_ci.. note::
107e66f31c5Sopenharmony_ci
108e66f31c5Sopenharmony_ci    You will have to run `udp-dhcp` as **root** since it uses well known port
109e66f31c5Sopenharmony_ci    numbers below 1024.
110e66f31c5Sopenharmony_ci
111e66f31c5Sopenharmony_ci.. rubric:: udp-dhcp/main.c - Setup and send UDP packets
112e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/udp-dhcp/main.c
113e66f31c5Sopenharmony_ci    :language: c
114e66f31c5Sopenharmony_ci    :linenos:
115e66f31c5Sopenharmony_ci    :lines: 7-11,104-
116e66f31c5Sopenharmony_ci    :emphasize-lines: 8,10-11,17-18,21
117e66f31c5Sopenharmony_ci
118e66f31c5Sopenharmony_ci.. note::
119e66f31c5Sopenharmony_ci
120e66f31c5Sopenharmony_ci    The IP address ``0.0.0.0`` is used to bind to all interfaces. The IP
121e66f31c5Sopenharmony_ci    address ``255.255.255.255`` is a broadcast address meaning that packets
122e66f31c5Sopenharmony_ci    will be sent to all interfaces on the subnet.  port ``0`` means that the OS
123e66f31c5Sopenharmony_ci    randomly assigns a port.
124e66f31c5Sopenharmony_ci
125e66f31c5Sopenharmony_ciFirst we setup the receiving socket to bind on all interfaces on port 68 (DHCP
126e66f31c5Sopenharmony_ciclient) and start a read on it. This will read back responses from any DHCP
127e66f31c5Sopenharmony_ciserver that replies. We use the UV_UDP_REUSEADDR flag to play nice with any
128e66f31c5Sopenharmony_ciother system DHCP clients that are running on this computer on the same port.
129e66f31c5Sopenharmony_ciThen we setup a similar send socket and use ``uv_udp_send`` to send
130e66f31c5Sopenharmony_cia *broadcast message* on port 67 (DHCP server).
131e66f31c5Sopenharmony_ci
132e66f31c5Sopenharmony_ciIt is **necessary** to set the broadcast flag, otherwise you will get an
133e66f31c5Sopenharmony_ci``EACCES`` error [#]_. The exact message being sent is not relevant to this
134e66f31c5Sopenharmony_cibook and you can study the code if you are interested. As usual the read and
135e66f31c5Sopenharmony_ciwrite callbacks will receive a status code of < 0 if something went wrong.
136e66f31c5Sopenharmony_ci
137e66f31c5Sopenharmony_ciSince UDP sockets are not connected to a particular peer, the read callback
138e66f31c5Sopenharmony_cireceives an extra parameter about the sender of the packet.
139e66f31c5Sopenharmony_ci
140e66f31c5Sopenharmony_ci``nread`` may be zero if there is no more data to be read. If ``addr`` is NULL,
141e66f31c5Sopenharmony_ciit indicates there is nothing to read (the callback shouldn't do anything), if
142e66f31c5Sopenharmony_cinot NULL, it indicates that an empty datagram was received from the host at
143e66f31c5Sopenharmony_ci``addr``. The ``flags`` parameter may be ``UV_UDP_PARTIAL`` if the buffer
144e66f31c5Sopenharmony_ciprovided by your allocator was not large enough to hold the data. *In this case
145e66f31c5Sopenharmony_cithe OS will discard the data that could not fit* (That's UDP for you!).
146e66f31c5Sopenharmony_ci
147e66f31c5Sopenharmony_ci.. rubric:: udp-dhcp/main.c - Reading packets
148e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/udp-dhcp/main.c
149e66f31c5Sopenharmony_ci    :language: c
150e66f31c5Sopenharmony_ci    :linenos:
151e66f31c5Sopenharmony_ci    :lines: 17-40
152e66f31c5Sopenharmony_ci    :emphasize-lines: 1,23
153e66f31c5Sopenharmony_ci
154e66f31c5Sopenharmony_ciUDP Options
155e66f31c5Sopenharmony_ci+++++++++++
156e66f31c5Sopenharmony_ci
157e66f31c5Sopenharmony_ciTime-to-live
158e66f31c5Sopenharmony_ci~~~~~~~~~~~~
159e66f31c5Sopenharmony_ci
160e66f31c5Sopenharmony_ciThe TTL of packets sent on the socket can be changed using ``uv_udp_set_ttl``.
161e66f31c5Sopenharmony_ci
162e66f31c5Sopenharmony_ciIPv6 stack only
163e66f31c5Sopenharmony_ci~~~~~~~~~~~~~~~
164e66f31c5Sopenharmony_ci
165e66f31c5Sopenharmony_ciIPv6 sockets can be used for both IPv4 and IPv6 communication. If you want to
166e66f31c5Sopenharmony_cirestrict the socket to IPv6 only, pass the ``UV_UDP_IPV6ONLY`` flag to
167e66f31c5Sopenharmony_ci``uv_udp_bind``.
168e66f31c5Sopenharmony_ci
169e66f31c5Sopenharmony_ciMulticast
170e66f31c5Sopenharmony_ci~~~~~~~~~
171e66f31c5Sopenharmony_ci
172e66f31c5Sopenharmony_ciA socket can (un)subscribe to a multicast group using:
173e66f31c5Sopenharmony_ci
174e66f31c5Sopenharmony_ci.. code::block:: c
175e66f31c5Sopenharmony_ci
176e66f31c5Sopenharmony_ci    int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, const char* interface_addr, uv_membership membership);
177e66f31c5Sopenharmony_ci
178e66f31c5Sopenharmony_ciwhere ``membership`` is ``UV_JOIN_GROUP`` or ``UV_LEAVE_GROUP``.
179e66f31c5Sopenharmony_ci
180e66f31c5Sopenharmony_ciThe concepts of multicasting are nicely explained in `this guide`_.
181e66f31c5Sopenharmony_ci
182e66f31c5Sopenharmony_ci.. _this guide: https://www.tldp.org/HOWTO/Multicast-HOWTO-2.html
183e66f31c5Sopenharmony_ci
184e66f31c5Sopenharmony_ciLocal loopback of multicast packets is enabled by default [#]_, use
185e66f31c5Sopenharmony_ci``uv_udp_set_multicast_loop`` to switch it off.
186e66f31c5Sopenharmony_ci
187e66f31c5Sopenharmony_ciThe packet time-to-live for multicast packets can be changed using
188e66f31c5Sopenharmony_ci``uv_udp_set_multicast_ttl``.
189e66f31c5Sopenharmony_ci
190e66f31c5Sopenharmony_ciQuerying DNS
191e66f31c5Sopenharmony_ci------------
192e66f31c5Sopenharmony_ci
193e66f31c5Sopenharmony_cilibuv provides asynchronous DNS resolution. For this it provides its own
194e66f31c5Sopenharmony_ci``getaddrinfo`` replacement [#]_. In the callback you can
195e66f31c5Sopenharmony_ciperform normal socket operations on the retrieved addresses. Let's connect to
196e66f31c5Sopenharmony_ciLibera.chat to see an example of DNS resolution.
197e66f31c5Sopenharmony_ci
198e66f31c5Sopenharmony_ci.. rubric:: dns/main.c
199e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/dns/main.c
200e66f31c5Sopenharmony_ci    :language: c
201e66f31c5Sopenharmony_ci    :linenos:
202e66f31c5Sopenharmony_ci    :lines: 61-
203e66f31c5Sopenharmony_ci    :emphasize-lines: 12
204e66f31c5Sopenharmony_ci
205e66f31c5Sopenharmony_ciIf ``uv_getaddrinfo`` returns non-zero, something went wrong in the setup and
206e66f31c5Sopenharmony_ciyour callback won't be invoked at all. All arguments can be freed immediately
207e66f31c5Sopenharmony_ciafter ``uv_getaddrinfo`` returns. The `hostname`, `servname` and `hints`
208e66f31c5Sopenharmony_cistructures are documented in `the getaddrinfo man page <getaddrinfo_>`_. The
209e66f31c5Sopenharmony_cicallback can be ``NULL`` in which case the function will run synchronously.
210e66f31c5Sopenharmony_ci
211e66f31c5Sopenharmony_ciIn the resolver callback, you can pick any IP from the linked list of ``struct
212e66f31c5Sopenharmony_ciaddrinfo(s)``. This also demonstrates ``uv_tcp_connect``. It is necessary to
213e66f31c5Sopenharmony_cicall ``uv_freeaddrinfo`` in the callback.
214e66f31c5Sopenharmony_ci
215e66f31c5Sopenharmony_ci.. rubric:: dns/main.c
216e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/dns/main.c
217e66f31c5Sopenharmony_ci    :language: c
218e66f31c5Sopenharmony_ci    :linenos:
219e66f31c5Sopenharmony_ci    :lines: 42-60
220e66f31c5Sopenharmony_ci    :emphasize-lines: 8,16
221e66f31c5Sopenharmony_ci
222e66f31c5Sopenharmony_cilibuv also provides the inverse `uv_getnameinfo`_.
223e66f31c5Sopenharmony_ci
224e66f31c5Sopenharmony_ci.. _uv_getnameinfo: http://docs.libuv.org/en/v1.x/dns.html#c.uv_getnameinfo
225e66f31c5Sopenharmony_ci
226e66f31c5Sopenharmony_ciNetwork interfaces
227e66f31c5Sopenharmony_ci------------------
228e66f31c5Sopenharmony_ci
229e66f31c5Sopenharmony_ciInformation about the system's network interfaces can be obtained through libuv
230e66f31c5Sopenharmony_ciusing ``uv_interface_addresses``. This simple program just prints out all the
231e66f31c5Sopenharmony_ciinterface details so you get an idea of the fields that are available. This is
232e66f31c5Sopenharmony_ciuseful to allow your service to bind to IP addresses when it starts.
233e66f31c5Sopenharmony_ci
234e66f31c5Sopenharmony_ci.. rubric:: interfaces/main.c
235e66f31c5Sopenharmony_ci.. literalinclude:: ../../code/interfaces/main.c
236e66f31c5Sopenharmony_ci    :language: c
237e66f31c5Sopenharmony_ci    :linenos:
238e66f31c5Sopenharmony_ci    :emphasize-lines: 9,17
239e66f31c5Sopenharmony_ci
240e66f31c5Sopenharmony_ci``is_internal`` is true for loopback interfaces. Note that if a physical
241e66f31c5Sopenharmony_ciinterface has multiple IPv4/IPv6 addresses, the name will be reported multiple
242e66f31c5Sopenharmony_citimes, with each address being reported once.
243e66f31c5Sopenharmony_ci
244e66f31c5Sopenharmony_ci.. _c-ares: https://c-ares.haxx.se
245e66f31c5Sopenharmony_ci.. _getaddrinfo: https://man7.org/linux/man-pages/man3/getaddrinfo.3.html
246e66f31c5Sopenharmony_ci
247e66f31c5Sopenharmony_ci.. _User Datagram Protocol: https://en.wikipedia.org/wiki/User_Datagram_Protocol
248e66f31c5Sopenharmony_ci.. _DHCP: https://tools.ietf.org/html/rfc2131
249e66f31c5Sopenharmony_ci
250e66f31c5Sopenharmony_ci----
251e66f31c5Sopenharmony_ci
252e66f31c5Sopenharmony_ci.. [#] https://beej.us/guide/bgnet/html/#broadcast-packetshello-world
253e66f31c5Sopenharmony_ci.. [#] https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html#ss6.1
254e66f31c5Sopenharmony_ci.. [#] libuv use the system ``getaddrinfo`` in the libuv threadpool. libuv
255e66f31c5Sopenharmony_ci    v0.8.0 and earlier also included c-ares_ as an alternative, but this has been
256e66f31c5Sopenharmony_ci    removed in v0.9.0.
257