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