diff third_party/libuv/docs/src/guide/networking.rst @ 160:948de3f54cea

[ThirdParty] Added libuv
author June Park <parkjune1995@gmail.com>
date Wed, 14 Jan 2026 19:39:52 -0800
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/third_party/libuv/docs/src/guide/networking.rst	Wed Jan 14 19:39:52 2026 -0800
@@ -0,0 +1,256 @@
+Networking
+==========
+
+Networking in libuv is not much different from directly using the BSD socket
+interface, some things are easier, all are non-blocking, but the concepts stay
+the same. In addition libuv offers utility functions to abstract the annoying,
+repetitive and low-level tasks like setting up sockets using the BSD socket
+structures, DNS lookup, and tweaking various socket parameters.
+
+The ``uv_tcp_t`` and ``uv_udp_t`` structures are used for network I/O.
+
+.. NOTE::
+
+  The code samples in this chapter exist to show certain libuv APIs. They are
+  not examples of good quality code. They leak memory and don't always close
+  connections properly.
+
+TCP
+---
+
+TCP is a connection oriented, stream protocol and is therefore based on the
+libuv streams infrastructure.
+
+Server
+++++++
+
+Server sockets proceed by:
+
+1. ``uv_tcp_init`` the TCP handle.
+2. ``uv_tcp_bind`` it.
+3. Call ``uv_listen`` on the handle to have a callback invoked whenever a new
+   connection is established by a client.
+4. Use ``uv_accept`` to accept the connection.
+5. Use :ref:`stream operations <buffers-and-streams>` to communicate with the
+   client.
+
+Here is a simple echo server
+
+.. rubric:: tcp-echo-server/main.c - The listen socket
+.. literalinclude:: ../../code/tcp-echo-server/main.c
+    :language: c
+    :linenos:
+    :lines: 68-
+    :emphasize-lines: 4-5,7-10
+
+You can see the utility function ``uv_ip4_addr`` being used to convert from
+a human readable IP address, port pair to the sockaddr_in structure required by
+the BSD socket APIs. The reverse can be obtained using ``uv_ip4_name``.
+
+.. NOTE::
+
+    There are ``uv_ip6_*`` analogues for the ip4 functions.
+
+Most of the setup functions are synchronous since they are CPU-bound.
+``uv_listen`` is where we return to libuv's callback style. The second
+arguments is the backlog queue -- the maximum length of queued connections.
+
+When a connection is initiated by clients, the callback is required to set up
+a handle for the client socket and associate the handle using ``uv_accept``.
+In this case we also establish interest in reading from this stream.
+
+.. rubric:: tcp-echo-server/main.c - Accepting the client
+.. literalinclude:: ../../code/tcp-echo-server/main.c
+    :language: c
+    :linenos:
+    :lines: 51-66
+    :emphasize-lines: 9-10
+
+The remaining set of functions is very similar to the streams example and can
+be found in the code. Just remember to call ``uv_close`` when the socket isn't
+required. This can be done even in the ``uv_listen`` callback if you are not
+interested in accepting the connection.
+
+Client
+++++++
+
+Where you do bind/listen/accept on the server, on the client side it's simply
+a matter of calling ``uv_tcp_connect``. The same ``uv_connect_cb`` style
+callback of ``uv_listen`` is used by ``uv_tcp_connect``. Try::
+
+    uv_tcp_t* socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
+    uv_tcp_init(loop, socket);
+
+    uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
+
+    struct sockaddr_in dest;
+    uv_ip4_addr("127.0.0.1", 80, &dest);
+
+    uv_tcp_connect(connect, socket, (const struct sockaddr*)&dest, on_connect);
+
+where ``on_connect`` will be called after the connection is established. The
+callback receives the ``uv_connect_t`` struct, which has a member ``.handle``
+pointing to the socket.
+
+UDP
+---
+
+The `User Datagram Protocol`_ offers connectionless, unreliable network
+communication. Hence libuv doesn't offer a stream. Instead libuv provides
+non-blocking UDP support via the `uv_udp_t` handle (for receiving) and
+`uv_udp_send_t` request (for sending) and related functions. That said, the
+actual API for reading/writing is very similar to normal stream reads. To look
+at how UDP can be used, the example shows the first stage of obtaining an IP
+address from a `DHCP`_ server -- DHCP Discover.
+
+.. note::
+
+    You will have to run `udp-dhcp` as **root** since it uses well known port
+    numbers below 1024.
+
+.. rubric:: udp-dhcp/main.c - Setup and send UDP packets
+.. literalinclude:: ../../code/udp-dhcp/main.c
+    :language: c
+    :linenos:
+    :lines: 7-11,104-
+    :emphasize-lines: 8,10-11,17-18,21
+
+.. note::
+
+    The IP address ``0.0.0.0`` is used to bind to all interfaces. The IP
+    address ``255.255.255.255`` is a broadcast address meaning that packets
+    will be sent to all interfaces on the subnet.  port ``0`` means that the OS
+    randomly assigns a port.
+
+First we setup the receiving socket to bind on all interfaces on port 68 (DHCP
+client) and start a read on it. This will read back responses from any DHCP
+server that replies. We use the UV_UDP_REUSEADDR flag to play nice with any
+other system DHCP clients that are running on this computer on the same port.
+Then we setup a similar send socket and use ``uv_udp_send`` to send
+a *broadcast message* on port 67 (DHCP server).
+
+It is **necessary** to set the broadcast flag, otherwise you will get an
+``EACCES`` error [#]_. The exact message being sent is not relevant to this
+book and you can study the code if you are interested. As usual the read and
+write callbacks will receive a status code of < 0 if something went wrong.
+
+Since UDP sockets are not connected to a particular peer, the read callback
+receives an extra parameter about the sender of the packet.
+
+``nread`` may be zero if there is no more data to be read. If ``addr`` is NULL,
+it indicates there is nothing to read (the callback shouldn't do anything), if
+not NULL, it indicates that an empty datagram was received from the host at
+``addr``. The ``flags`` parameter may be ``UV_UDP_PARTIAL`` if the buffer
+provided by your allocator was not large enough to hold the data. *In this case
+the OS will discard the data that could not fit* (That's UDP for you!).
+
+.. rubric:: udp-dhcp/main.c - Reading packets
+.. literalinclude:: ../../code/udp-dhcp/main.c
+    :language: c
+    :linenos:
+    :lines: 17-40
+    :emphasize-lines: 1,23
+
+UDP Options
++++++++++++
+
+Time-to-live
+~~~~~~~~~~~~
+
+The TTL of packets sent on the socket can be changed using ``uv_udp_set_ttl``.
+
+IPv6 stack only
+~~~~~~~~~~~~~~~
+
+IPv6 sockets can be used for both IPv4 and IPv6 communication. If you want to
+restrict the socket to IPv6 only, pass the ``UV_UDP_IPV6ONLY`` flag to
+``uv_udp_bind``.
+
+Multicast
+~~~~~~~~~
+
+A socket can (un)subscribe to a multicast group using:
+
+.. code::block:: c
+
+    int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, const char* interface_addr, uv_membership membership);
+
+where ``membership`` is ``UV_JOIN_GROUP`` or ``UV_LEAVE_GROUP``.
+
+The concepts of multicasting are nicely explained in `this guide`_.
+
+.. _this guide: https://www.tldp.org/HOWTO/Multicast-HOWTO-2.html
+
+Local loopback of multicast packets is enabled by default [#]_, use
+``uv_udp_set_multicast_loop`` to switch it off.
+
+The packet time-to-live for multicast packets can be changed using
+``uv_udp_set_multicast_ttl``.
+
+Querying DNS
+------------
+
+libuv provides asynchronous DNS resolution. For this it provides its own
+``getaddrinfo`` replacement [#]_. In the callback you can
+perform normal socket operations on the retrieved addresses. Let's connect to
+Libera.chat to see an example of DNS resolution.
+
+.. rubric:: dns/main.c
+.. literalinclude:: ../../code/dns/main.c
+    :language: c
+    :linenos:
+    :lines: 61-
+    :emphasize-lines: 12
+
+If ``uv_getaddrinfo`` returns non-zero, something went wrong in the setup and
+your callback won't be invoked at all. All arguments can be freed immediately
+after ``uv_getaddrinfo`` returns. The `hostname`, `servname` and `hints`
+structures are documented in `the getaddrinfo man page <getaddrinfo_>`_. The
+callback can be ``NULL`` in which case the function will run synchronously.
+
+In the resolver callback, you can pick any IP from the linked list of ``struct
+addrinfo(s)``. This also demonstrates ``uv_tcp_connect``. It is necessary to
+call ``uv_freeaddrinfo`` in the callback.
+
+.. rubric:: dns/main.c
+.. literalinclude:: ../../code/dns/main.c
+    :language: c
+    :linenos:
+    :lines: 42-60
+    :emphasize-lines: 8,16
+
+libuv also provides the inverse `uv_getnameinfo`_.
+
+.. _uv_getnameinfo: http://docs.libuv.org/en/v1.x/dns.html#c.uv_getnameinfo
+
+Network interfaces
+------------------
+
+Information about the system's network interfaces can be obtained through libuv
+using ``uv_interface_addresses``. This simple program just prints out all the
+interface details so you get an idea of the fields that are available. This is
+useful to allow your service to bind to IP addresses when it starts.
+
+.. rubric:: interfaces/main.c
+.. literalinclude:: ../../code/interfaces/main.c
+    :language: c
+    :linenos:
+    :emphasize-lines: 9,17
+
+``is_internal`` is true for loopback interfaces. Note that if a physical
+interface has multiple IPv4/IPv6 addresses, the name will be reported multiple
+times, with each address being reported once.
+
+.. _c-ares: https://c-ares.haxx.se
+.. _getaddrinfo: https://man7.org/linux/man-pages/man3/getaddrinfo.3.html
+
+.. _User Datagram Protocol: https://en.wikipedia.org/wiki/User_Datagram_Protocol
+.. _DHCP: https://tools.ietf.org/html/rfc2131
+
+----
+
+.. [#] https://beej.us/guide/bgnet/html/#broadcast-packetshello-world
+.. [#] https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html#ss6.1
+.. [#] libuv use the system ``getaddrinfo`` in the libuv threadpool. libuv
+    v0.8.0 and earlier also included c-ares_ as an alternative, but this has been
+    removed in v0.9.0.