~donmcc/ood

38cc0398321ed19b9bc10eb7d1ac4662bda367e9 — Don McCaughey 10 months ago 52c85fb
Add more wrappers for functions that use `sockaddr` structs.

Added `sa_alloc()` to allocate an empty `sa_address` union.

Added `sa_accept_alloc()`, `sa_alloc_getpeername()` and
`sa_alloc_getsockname()` wrappers around `accept()`, `getpeername()` and
`getsockname()` respectively.

Updated `ood_inet_socket_accept()` to use `sa_accept_alloc()`.
5 files changed, 103 insertions(+), 15 deletions(-)

M TODO.md
M src/libood/ood/inet/socket.c
M src/sa/sa.c
M src/sa/sa.h
M src/sa/sa_tests.c
M TODO.md => TODO.md +1 -0
@@ 1,5 1,6 @@
# TODO

- in "sa", replace alloc functions with init functions
- check if `bind()` works with sizeof struct sockaddr_storage 
- test listening on unix and ipv6 sockets
- handle linux "unnamed" and "abstract" unix sockets

M src/libood/ood/inet/socket.c => src/libood/ood/inet/socket.c +9 -14
@@ 9,19 9,16 @@


static struct ood_inet_socket *
alloc_connection(int socket, struct sockaddr_in const *inet_address)
alloc_connection(int socket, union sa_address *address)
{
    assert(socket >= 0);

    struct ood_inet_socket *connection = calloc(1, sizeof(struct ood_inet_socket));
    if (connection) {
        connection->fd = socket;
        connection->address = sa_alloc_from_sockaddr_in(inet_address);
        if (!connection->address) {
            free(connection);
            return NULL;
        }
    }
    if (!connection) return NULL;

    connection->fd = socket;
    connection->address = address;

    return connection;
}



@@ 40,14 37,12 @@ ood_inet_socket_accept(struct ood_inet_socket *listener, struct ood_inet_socket 
    assert(listener);
    assert(connection_out);

    struct sockaddr_in client_address;
    socklen_t client_address_size = sizeof client_address;
    union sa_address *client_address;

    errno = 0;
    int fd = accept(listener->fd, (struct sockaddr *)&client_address, &client_address_size);
    int fd = sa_accept_alloc(listener->fd, &client_address);
    if (fd >= 0) {
        assert(AF_INET == client_address.sin_family);
        *connection_out = alloc_connection(fd, &client_address);
        *connection_out = alloc_connection(fd, client_address);
        if (*connection_out) {
            return ood_okay;
        } else {

M src/sa/sa.c => src/sa/sa.c +60 -0
@@ 7,6 7,13 @@


union sa_address *
sa_alloc(void)
{
    return calloc(1, sizeof(union sa_address));
}


union sa_address *
sa_alloc_from_in_addr_and_port(in_addr_t in_addr, in_port_t port)
{
    struct sockaddr_in ipv4_address = {


@@ 150,6 157,57 @@ sa_alloc_from_sockaddr_un(struct sockaddr_un const *local_address)
}


int
sa_accept_alloc(int socket, union sa_address **address_out)
{
    union sa_address *address = sa_alloc();
    if (!address) return -1;

    socklen_t len = sizeof(struct sockaddr_storage);
    int accepted = accept(socket, &address->generic, &len);
    if (accepted >= 0) {
        *address_out = address;
    } else {
        free(address);
    }
    return accepted;
}


union sa_address *
sa_alloc_getpeername(int socket)
{
    union sa_address *address = sa_alloc();
    if (!address) return NULL;

    socklen_t len = sizeof(struct sockaddr_storage);
    int result = getpeername(socket, &address->generic, &len);
    if (0 != result) {
        free(address);
        return NULL;
    }

    return address;
}


union sa_address *
sa_alloc_getsockname(int socket)
{
    union sa_address *address = sa_alloc();
    if (!address) return NULL;

    socklen_t len = sizeof(struct sockaddr_storage);
    int result = getsockname(socket, &address->generic, &len);
    if (0 != result) {
        free(address);
        return NULL;
    }

    return address;
}


socklen_t
sa_len(union sa_address const *address)
{


@@ 179,8 237,10 @@ sa_str(union sa_address const *address)
    }
}


extern int
sa_bind(int socket, union sa_address const *address);


extern int
sa_connect(int socket, union sa_address const *address);

M src/sa/sa.h => src/sa/sa.h +16 -1
@@ 49,6 49,9 @@ union sa_address {

// # Allocate socket address from components

union sa_address *
sa_alloc(void);

// `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 port);


@@ 69,7 72,7 @@ union sa_address *
sa_alloc_from_path(char const *path);


// # Allocate socket address from a `sockaddr`-type struct.
// # Allocate socket address from a `sockaddr`-type struct

union sa_address *
sa_alloc_from_sockaddr(struct sockaddr const *generic_address);


@@ 84,6 87,18 @@ union sa_address *
sa_alloc_from_sockaddr_un(struct sockaddr_un const *local_address);


// # Allocate socket address from a socket

int
sa_accept_alloc(int socket, union sa_address **address_out);

union sa_address *
sa_alloc_getpeername(int socket);

union sa_address *
sa_alloc_getsockname(int socket);


// # Get info about a socket address

socklen_t

M src/sa/sa_tests.c => src/sa/sa_tests.c +17 -0
@@ 9,6 9,21 @@


static void
test_sa_alloc(void)
{
    union sa_address *address = sa_alloc();

    assert(address);
    assert(AF_UNSPEC == address->generic.sa_family);
    assert(AF_UNSPEC == address->ipv4.sin_family);
    assert(AF_UNSPEC == address->ipv6.sin6_family);
    assert(AF_UNSPEC == address->local.sun_family);
    assert(AF_UNSPEC == address->storage.ss_family);

    free(address);
}

static void
test_sa_alloc_from_in_addr_and_port(void)
{
    union sa_address *address = sa_alloc_from_in_addr_and_port(INADDR_LOOPBACK, 8080);


@@ 476,6 491,8 @@ test_sa_str_for_null(void)
int
main(int argc, char *argv[])
{
    test_sa_alloc();

    test_sa_alloc_from_in_addr_and_port();
    test_sa_alloc_from_in6_addr_and_port();