~donmcc/sa

A wrapper around the polymorphic sockaddr family of structs
Extract common `from_ip_and_port_str()` function.
Add function `sa_find_port_in_str()`.
Rename parameters of `sa_from_ipv4_and_port_str()`.

refs

main
browse  log 

clone

read-only
https://git.sr.ht/~donmcc/sa
read/write
git@git.sr.ht:~donmcc/sa

You can also use your local clone with git send-email.

#SA: Socket Addresses

A wrapper around the polymorphic sockaddr family of structs and a set of helper functions for common socket address chores.

builds.sr.ht status

#Overview

The sa union holds storage for each of the sockaddr type puns along with space for a string representation. For the sockaddr_un address type, the sun_path field is used as the string representation.

The union contains fields .ipv4, .ipv6 and .local which correspond to structs sockaddr_in, sockaddr_in6 and sockaddr_un respectively. Additionally, .generic corresponds to a sockaddr struct and .storage to a sockaddr_storage struct.

union sa {
    struct sockaddr generic;
    struct {
        struct sockaddr_in ipv4;
        char ipv4_str[SA_IPV4_STR_SIZE];
    };
    struct {
        struct sockaddr_in6 ipv6;
        char ipv6_str[SA_IPV6_STR_SIZE];
    };
    struct sockaddr_un local;
    struct sockaddr_storage storage;
};

NB: Because the symbol unix is #defined in some Unix C compilers, sa uses the name local for Unix domain sockets (often referred to as "local" sockets).

The inline function sa_family() returns the discriminant value which tells which field is currently active. In an initialized sa union, the family will be either AF_UNSPEC, indicating a blank or zeroed-out sa union, or one of AF_INET, AF_INET6 or AF_UNIX.

Typical usage of sa looks like this (sans error handling):

// initialize a socket address for use
union sa address;
sa_from_ipv4_str_and_port(&address, "127.0.0.1", 8080);
bind(fd, &address.generic, sa_len(&address));

// receive a socket address
union sa client_address;
socklen_t len;
sa_prepare(&client_address, &len);
int client_fd = accept(fd, &client_address.generic, &len);
sa_update(&client_address);

Socket addresses are frequently logged, so sa creates a string representation at initialization time. Use the sa_str() function to get the correct string representation.

union sa address;
sa_from_in_addr_and_port(&address, INADDR_LOOPBACK, 8080);
printf("%s", sa_str(&address));
// prints "127.0.0.1:8080"

#License

SA is available under a BSD-style license. See the LICENSE file for details.

#Building From Source

SA is tested on macOS, Linux, FreeBSD and OpenBSD. Building it requires a C toolchain and CMake 3.13 or later.

git clone https://git.sr.ht/~donmcc/sa
cd sa
cmake -S . -B tmp
cmake --build tmp --target all test

#Build Options

To build with the Address Sanitizer enabled, set the ADDRESS_SANITIZER option to ON.

cmake -S . -B tmp -DADDRESS_SANITIZER=ON

Mac users note that the clang that ships with Xcode accepts the -fsanitize=address flag, but doesn't actually include the Address Sanitizer.

Set the COVERAGE option to ON to generate coverage files.

cmake -S . -B tmp -DCOVERAGE=ON

Set the WALL option to ON turns on additional warnings using the -Wall compiler option and treats warnings as errors. WALL is off by default but should be turned on for development and integration builds.

cmake -S . -B tmp -DCOVERAGE=ON -DWALL=ON