~donmcc/ood

3e6ca8c5f529c003fbc8efb584cc2e0d421ae955 — Don McCaughey 10 months ago 1a1afc8
Add functions that accept IP string addresses.

New functions `sa_alloc_from_ipv4_str_and_port()` and
`sa_alloc_from_ipv6_str_and_port()` take a IP address string as the
first argument and return NULL if the address cannot be parsed.
3 files changed, 78 insertions(+), 6 deletions(-)

M src/sa/sa.c
M src/sa/sa.h
M src/sa/sa_tests.c
M src/sa/sa.c => src/sa/sa.c +26 -4
@@ 7,30 7,52 @@


union sa_address *
sa_alloc_from_in_addr_and_port(in_addr_t in_addr, in_port_t in_port)
sa_alloc_from_in_addr_and_port(in_addr_t in_addr, in_port_t port)
{
    struct sockaddr_in ipv4_address = {
            .sin_family = AF_INET,
            .sin_addr.s_addr = htonl(in_addr),
            .sin_port = htons(in_port),
            .sin_port = htons(port),
    };
    return sa_alloc_from_sockaddr_in(&ipv4_address);
}


union sa_address *
sa_alloc_from_in6_addr_and_port(struct in6_addr in6_addr, in_port_t in_port)
sa_alloc_from_in6_addr_and_port(struct in6_addr in6_addr, in_port_t port)
{
    struct sockaddr_in6 inet6 = {
            .sin6_family=AF_INET6,
            .sin6_addr=in6_addr,
            .sin6_port=htons(in_port),
            .sin6_port=htons(port),
    };
    return sa_alloc_from_sockaddr_in6(&inet6);
}


union sa_address *
sa_alloc_from_ipv4_str_and_port(char const *ipv4_str, in_port_t port)
{
    in_addr_t in_addr;
    int result = inet_pton(AF_INET, ipv4_str, &in_addr);
    if (1 != result) return NULL;

    return sa_alloc_from_in_addr_and_port(ntohl(in_addr), port);
}


union sa_address *
sa_alloc_from_ipv6_str_and_port(char const *ipv6_str, in_port_t port)
{
    struct in6_addr in6_addr;
    int result = inet_pton(AF_INET6, ipv6_str, &in6_addr);
    if (1 != result) return NULL;

    return sa_alloc_from_in6_addr_and_port(in6_addr, port);
}


union sa_address *
sa_alloc_from_path(char const *path)
{
    if (!path) return NULL;

M src/sa/sa.h => src/sa/sa.h +12 -2
@@ 49,11 49,21 @@ union sa_address {

// # Allocate socket address from components

// `in_addr` and `port` are in host byte order
union sa_address *
sa_alloc_from_in_addr_and_port(in_addr_t in_addr, in_port_t in_port);
sa_alloc_from_in_addr_and_port(in_addr_t in_addr, in_port_t port);

// `port` is in host byte order
union sa_address *
sa_alloc_from_in6_addr_and_port(struct in6_addr in6_addr, in_port_t in_port);
sa_alloc_from_in6_addr_and_port(struct in6_addr in6_addr, in_port_t port);

// `port` is in host byte order
union sa_address *
sa_alloc_from_ipv4_str_and_port(char const *ipv4_str, in_port_t port);

// `port` is in host byte order
union sa_address *
sa_alloc_from_ipv6_str_and_port(char const *ipv6_str, in_port_t port);

union sa_address *
sa_alloc_from_path(char const *path);

M src/sa/sa_tests.c => src/sa/sa_tests.c +40 -0
@@ 47,6 47,44 @@ test_sa_alloc_from_in6_addr_and_port(void)


static void
test_sa_alloc_from_ipv4_str_and_port(void)
{
    union sa_address *address = sa_alloc_from_ipv4_str_and_port("127.0.0.1", 8080);

    assert(address);
    assert(AF_INET == address->generic.sa_family);
    assert(AF_INET == address->ipv4.sin_family);
    assert(AF_INET == address->ipv6.sin6_family);
    assert(AF_INET == address->local.sun_family);
    assert(AF_INET == address->storage.ss_family);
    assert(htonl(INADDR_LOOPBACK) == address->ipv4.sin_addr.s_addr);
    assert(htons(8080) == address->ipv4.sin_port);
    assert(STR_EQ("127.0.0.1:8080", sa_str(address)));

    free(address);
}


static void
test_sa_alloc_from_ipv6_str_and_port(void)
{
    union sa_address *address = sa_alloc_from_ipv6_str_and_port("::1", 8080);

    assert(address);
    assert(AF_INET6 == address->generic.sa_family);
    assert(AF_INET6 == address->ipv4.sin_family);
    assert(AF_INET6 == address->ipv6.sin6_family);
    assert(AF_INET6 == address->local.sun_family);
    assert(AF_INET6 == address->storage.ss_family);
    assert(IN6_ADDR_EQ(&in6addr_loopback, &address->ipv6.sin6_addr));
    assert(htons(8080) == address->ipv6.sin6_port);
    assert(STR_EQ("::1:8080", sa_str(address)));

    free(address);
}


static void
test_sa_alloc_from_path(void)
{
    union sa_address *address = sa_alloc_from_path("/var/dood/http");


@@ 354,6 392,8 @@ main(int argc, char *argv[])
{
    test_sa_alloc_from_in_addr_and_port();
    test_sa_alloc_from_in6_addr_and_port();
    test_sa_alloc_from_ipv4_str_and_port();
    test_sa_alloc_from_ipv6_str_and_port();
    test_sa_alloc_from_path();
    test_sa_alloc_from_path_when_null();
    test_sa_alloc_from_path_when_too_long();