M src/dood/main.c => src/dood/main.c +3 -3
@@ 34,7 34,7 @@ connection_on_error(struct ood_inet_socket *connection)
assert(connection->data);
struct server *server = connection->data;
- fprintf(stderr, "dood: error on connection to %s\n", sa_str(connection->address));
+ fprintf(stderr, "dood: error on connection to %s\n", sa_str(&connection->address));
server_close_socket(server, connection);
}
@@ 109,7 109,7 @@ listener_on_error(struct ood_inet_socket *listener)
assert(listener->data);
struct server *server = listener->data;
- fprintf(stderr, "dood: error listening on %s\n", sa_str(listener->address));
+ fprintf(stderr, "dood: error listening on %s\n", sa_str(&listener->address));
server_close_socket(server, listener);
}
@@ 134,7 134,7 @@ listener_on_read(struct ood_inet_socket *listener)
connection->data = server;
server_add_socket(server, connection);
- printf("dood: accepted connection from %s\n", sa_str(connection->address));
+ printf("dood: accepted connection from %s\n", sa_str(&connection->address));
}
}
M src/dood/server.c => src/dood/server.c +2 -2
@@ 34,7 34,7 @@ server_add_listener(struct server *server,
return ood_error;
}
- printf("dood: listening on %s\n", sa_str(listener->address));
+ printf("dood: listening on %s\n", sa_str(&listener->address));
return ood_okay;
}
@@ 85,7 85,7 @@ server_close_all_listeners(struct server *server)
if (!server->sockets->items[i]) continue;
struct ood_inet_socket *socket = (struct ood_inet_socket *)server->sockets->items[i];
if (OOD_INET_SOCKET_FLAGS_LISTENING & socket->flags) {
- printf("dood: no longer listening on %s\n", sa_str(socket->address));
+ printf("dood: no longer listening on %s\n", sa_str(&socket->address));
ood_inet_socket_free(socket);
server->sockets->items = NULL;
--server->sockets->count;
M src/libood/ood/inet/socket.c => src/libood/ood/inet/socket.c +8 -11
@@ 17,7 17,7 @@ alloc_connection(int socket, union sa *address)
if (!connection) return NULL;
connection->fd = socket;
- connection->address = address;
+ connection->address = *address;
return connection;
}
@@ 37,12 37,14 @@ ood_inet_socket_accept(struct ood_inet_socket *listener, struct ood_inet_socket
assert(listener);
assert(connection_out);
- union sa *client_address;
+ union sa client_address;
+ socklen_t len;
+ sa_prepare(&client_address, &len);
errno = 0;
- int fd = sa_accept_alloc(listener->fd, &client_address);
+ int fd = accept(listener->fd, &client_address.generic, &len);
if (fd >= 0) {
- *connection_out = alloc_connection(fd, client_address);
+ *connection_out = alloc_connection(fd, &client_address);
if (*connection_out) {
return ood_okay;
} else {
@@ 66,11 68,7 @@ ood_inet_socket_alloc(in_addr_t in_addr, in_port_t in_port)
if (!listener) return NULL;
listener->fd = -1;
- listener->address = sa_alloc_from_in_addr_and_port(in_addr, in_port);
- if (!listener->address) {
- free(listener);
- return NULL;
- }
+ sa_from_in_addr_and_port(&listener->address, in_addr, in_port);
return listener;
}
@@ 81,7 79,6 @@ ood_inet_socket_free(struct ood_inet_socket *socket)
{
if (socket) {
if (socket->fd >= 0) close(socket->fd);
- free(socket->address);
free(socket);
}
}
@@ 111,7 108,7 @@ ood_inet_socket_listen(struct ood_inet_socket *listener, int backlog)
return ood_error;
}
- int result = sa_bind(listener->fd, listener->address);
+ int result = bind(listener->fd, &listener->address.generic, sa_len(&listener->address));
if (result < 0) {
close_socket(listener);
return ood_error;
M src/libood/ood/inet/socket.h => src/libood/ood/inet/socket.h +2 -1
@@ 3,6 3,7 @@
#include <netinet/in.h>
+#include <sa.h>
#define OOD_INET_SOCKET_FLAGS_LISTENING 0x00000001
@@ 19,7 20,7 @@ typedef void
struct ood_inet_socket {
int fd;
uint32_t flags;
- union sa *address;
+ union sa address;
void *data;
ood_inet_socket_fn *on_error;
ood_inet_socket_fn *on_read;
M src/libood/ood/inet/socket_test.c => src/libood/ood/inet/socket_test.c +3 -3
@@ 11,9 11,9 @@ test_inet_socket_alloc(void)
assert(listener);
assert(-1 == listener->fd);
- assert(htonl(INADDR_LOOPBACK) == listener->address->ipv4.sin_addr.s_addr);
- assert(htons(1080) == listener->address->ipv4.sin_port);
- assert(0 == strcmp("127.0.0.1:1080", sa_str(listener->address)));
+ assert(htonl(INADDR_LOOPBACK) == listener->address.ipv4.sin_addr.s_addr);
+ assert(htons(1080) == listener->address.ipv4.sin_port);
+ assert(0 == strcmp("127.0.0.1:1080", sa_str(&listener->address)));
ood_inet_socket_free(listener);
}
M src/sa/sa.c => src/sa/sa.c +63 -121
@@ 6,52 6,54 @@
#include <stdio.h>
-union sa *
-sa_alloc(void)
+bool
+sa_unspec(union sa *address)
{
- return calloc(1, sizeof(union sa));
+ if (!address) return false;
+ memset(address, 0, sizeof(union sa));
+ return true;
}
-union sa *
-sa_alloc_from_in_addr_and_port(in_addr_t in_addr, in_port_t port)
+bool
+sa_from_in_addr_and_port(union sa *address, 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(port),
};
- return sa_alloc_from_sockaddr_in(&ipv4_address);
+ return sa_from_sockaddr_in(address, &ipv4_address);
}
-union sa *
-sa_alloc_from_in6_addr_and_port(struct in6_addr in6_addr, in_port_t port)
+bool
+sa_from_in6_addr_and_port(union sa *address, struct in6_addr in6_addr, in_port_t port)
{
struct sockaddr_in6 inet6 = {
.sin6_family=AF_INET6,
.sin6_addr=in6_addr,
.sin6_port=htons(port),
};
- return sa_alloc_from_sockaddr_in6(&inet6);
+ return sa_from_sockaddr_in6(address, &inet6);
}
-union sa *
-sa_alloc_from_ipv4_str_and_port(char const *ipv4_str, in_port_t port)
+bool
+sa_from_ipv4_str_and_port(union sa *address, char const *ipv4_str, in_port_t port)
{
- if (!ipv4_str) return NULL;
+ if (!ipv4_str) return false;
in_addr_t in_addr;
int result = inet_pton(AF_INET, ipv4_str, &in_addr);
- if (1 != result) return NULL;
+ if (1 != result) return false;
- return sa_alloc_from_in_addr_and_port(ntohl(in_addr), port);
+ return sa_from_in_addr_and_port(address, ntohl(in_addr), port);
}
-union sa *
-sa_alloc_from_ipv6_str_and_port(char const *ipv6_str, in_port_t port)
+bool
+sa_from_ipv6_str_and_port(union sa *address, char const *ipv6_str, in_port_t port)
{
if (!ipv6_str) return NULL;
@@ 59,152 61,100 @@ sa_alloc_from_ipv6_str_and_port(char const *ipv6_str, in_port_t port)
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);
+ return sa_from_in6_addr_and_port(address, in6_addr, port);
}
-union sa *
-sa_alloc_from_path(char const *path)
+bool
+sa_from_path(union sa *address, char const *path)
{
- if (!path) return NULL;
- if (strlen(path) >= UNIX_PATH_MAX) return NULL;
+ if (!path) return false;
+ if (strlen(path) >= UNIX_PATH_MAX) return false;
struct sockaddr_un local_address = {
.sun_family=AF_UNIX,
};
strcpy(local_address.sun_path, path);
- return sa_alloc_from_sockaddr_un(&local_address);
+ return sa_from_sockaddr_un(address, &local_address);
}
-union sa *
-sa_alloc_from_sockaddr(struct sockaddr const *generic_address)
+bool
+sa_from_sockaddr(union sa *address, struct sockaddr const *generic_address)
{
- if (!generic_address) return NULL;
+ if (!generic_address) return false;
switch (generic_address->sa_family) {
- case AF_UNIX: return sa_alloc_from_sockaddr_un((struct sockaddr_un const *)generic_address);
- case AF_INET: return sa_alloc_from_sockaddr_in((struct sockaddr_in const *)generic_address);
- case AF_INET6: return sa_alloc_from_sockaddr_in6((struct sockaddr_in6 const *)generic_address);
- default: return NULL;
+ case AF_UNIX: return sa_from_sockaddr_un(address, (struct sockaddr_un const *)generic_address);
+ case AF_INET: return sa_from_sockaddr_in(address, (struct sockaddr_in const *)generic_address);
+ case AF_INET6: return sa_from_sockaddr_in6(address, (struct sockaddr_in6 const *)generic_address);
+ default: return false;
}
}
-union sa *
-sa_alloc_from_sockaddr_in(struct sockaddr_in const *ipv4_address)
+bool
+sa_from_sockaddr_in(union sa *address, struct sockaddr_in const *ipv4_address)
{
- if (!ipv4_address) return NULL;
+ if (!ipv4_address) return false;
- union sa *address = calloc(1, sizeof(union sa));
- if (!address) return NULL;
+ if (!sa_unspec(address)) return false;
address->ipv4 = *ipv4_address;
- const char *wrote_address = inet_ntop(AF_INET, &ipv4_address->sin_addr,
- address->ipv4_str, SA_IPV4_STR_SIZE);
- if (!wrote_address) goto fail;
-
- char *s = address->ipv4_str + strlen(address->ipv4_str);
- int wrote_port = sprintf(s, ":%i", ntohs(ipv4_address->sin_port));
- if (wrote_port < 0) goto fail;
- return address;
+ const char *ipv4_str = inet_ntop(AF_INET, &ipv4_address->sin_addr,
+ address->ipv4_str, SA_IPV4_STR_SIZE);
+ if (!ipv4_str) return false;
- fail:
- free(address);
- return NULL;
+ char *s = address->ipv4_str + strlen(address->ipv4_str);
+ int bytes_written = sprintf(s, ":%i", ntohs(ipv4_address->sin_port));
+ if (bytes_written < 0) return false;
+ return true;
}
-union sa *
-sa_alloc_from_sockaddr_in6(struct sockaddr_in6 const *ipv6_address)
+bool
+sa_from_sockaddr_in6(union sa *address, struct sockaddr_in6 const *ipv6_address)
{
- if (!ipv6_address) return NULL;
+ if (!ipv6_address) return false;
- union sa *address = calloc(1, sizeof(union sa));
- if (!address) return NULL;
+ if (!sa_unspec(address)) return false;
address->ipv6 = *ipv6_address;
- char const *wrote_address = inet_ntop(AF_INET6, &ipv6_address->sin6_addr,
- address->ipv6_str, SA_IPV6_STR_SIZE);
- if (!wrote_address) goto fail;
+ char const *ipv6_str = inet_ntop(AF_INET6, &ipv6_address->sin6_addr,
+ address->ipv6_str, SA_IPV6_STR_SIZE);
+ if (!ipv6_str) return false;
char *s = address->ipv6_str + strlen(address->ipv6_str);
- int wrote_port = sprintf(s, ":%i", ntohs(ipv6_address->sin6_port));
- if (wrote_port < 0) goto fail;
-
- return address;
+ int bytes_written = sprintf(s, ":%i", ntohs(ipv6_address->sin6_port));
+ if (bytes_written < 0) return false;
- fail:
- free(address);
- return NULL;
+ return true;
}
-union sa *
-sa_alloc_from_sockaddr_un(struct sockaddr_un const *local_address)
+bool
+sa_from_sockaddr_un(union sa *address, struct sockaddr_un const *local_address)
{
- if (!local_address) return NULL;
+ if (!local_address) return false;
- union sa *address = calloc(1, sizeof(union sa));
- if (!address) return NULL;
+ if (!sa_unspec(address)) return false;
address->local = *local_address;
- return address;
-}
-
-
-int
-sa_accept_alloc(int socket, union sa **address_out)
-{
- union sa *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 *
-sa_alloc_getpeername(int socket)
-{
- union sa *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;
+ return true;
}
-union sa *
-sa_alloc_getsockname(int socket)
+bool
+sa_prepare(union sa *address, socklen_t *len)
{
- union sa *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;
+ if (!sa_unspec(address)) return false;
+ if (!len) return false;
+ *len = sa_len(address);
+ return true;
}
@@ 236,11 186,3 @@ sa_str(union sa const *address)
default: return "(unsupported)";
}
}
-
-
-extern int
-sa_bind(int socket, union sa const *address);
-
-
-extern int
-sa_connect(int socket, union sa const *address);
M src/sa/sa.h => src/sa/sa.h +44 -49
@@ 2,6 2,7 @@
#define SA_H_INCLUDED
+#include <stdbool.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ 29,9 30,22 @@
a string representation. For the `sockaddr_un` address type, the `sun_path`
field is used as the string representation.
+ Typical usage of `sa` looks like this (sans error handling):
+
+ // initializing 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));
+
+ // receiving a socket address
+ union sa client_address;
+ socklen_t len;
+ sa_prepare(&client_address, &len);
+ int client_fd = accept(fd, &client_address.generic, &len);
+
Because the symbol `unix` is #defined in some Unix C compilers, `sa`
- uses the name `local` to refer to Unix domain sockets, which are sometimes
- referred to as "local" sockets. */
+ uses the name `local` for Unix domain sockets (often referred to as "local"
+ sockets). */
union sa {
struct sockaddr generic;
struct {
@@ 47,56 61,52 @@ union sa {
};
-// # Allocate socket address from components
+// # Initialize an unspecified socket address
-union sa *
-sa_alloc(void);
+bool
+sa_unspec(union sa *address);
-// `in_addr` and `port` are in host byte order
-union sa *
-sa_alloc_from_in_addr_and_port(in_addr_t in_addr, in_port_t port);
-// `port` is in host byte order
-union sa *
-sa_alloc_from_in6_addr_and_port(struct in6_addr in6_addr, in_port_t port);
+// # Initialize a socket address from components
-// `port` is in host byte order
-union sa *
-sa_alloc_from_ipv4_str_and_port(char const *ipv4_str, in_port_t port);
+bool
+sa_from_in_addr_and_port(union sa *address, in_addr_t in_addr, in_port_t port);
// `port` is in host byte order
-union sa *
-sa_alloc_from_ipv6_str_and_port(char const *ipv6_str, in_port_t port);
+bool
+sa_from_in6_addr_and_port(union sa *address, struct in6_addr in6_addr, in_port_t port);
-union sa *
-sa_alloc_from_path(char const *path);
+// `port` is in host byte order
+bool
+sa_from_ipv4_str_and_port(union sa *address, char const *ipv4_str, in_port_t port);
+// `port` is in host byte order
+bool
+sa_from_ipv6_str_and_port(union sa *address, char const *ipv6_str, in_port_t port);
-// # Allocate socket address from a `sockaddr`-type struct
+bool
+sa_from_path(union sa *address, char const *path);
-union sa *
-sa_alloc_from_sockaddr(struct sockaddr const *generic_address);
-union sa *
-sa_alloc_from_sockaddr_in(struct sockaddr_in const *ipv4_address);
+// # Initialize socket address from a `sockaddr`-type struct
-union sa *
-sa_alloc_from_sockaddr_in6(struct sockaddr_in6 const *ipv6_address);
+bool
+sa_from_sockaddr(union sa *address, struct sockaddr const *generic_address);
-union sa *
-sa_alloc_from_sockaddr_un(struct sockaddr_un const *local_address);
+bool
+sa_from_sockaddr_in(union sa *address, struct sockaddr_in const *ipv4_address);
+bool
+sa_from_sockaddr_in6(union sa *address, struct sockaddr_in6 const *ipv6_address);
-// # Allocate socket address from a socket
+bool
+sa_from_sockaddr_un(union sa *address, struct sockaddr_un const *local_address);
-int
-sa_accept_alloc(int socket, union sa **address_out);
-union sa *
-sa_alloc_getpeername(int socket);
+// # Initialize an `sa` union and length for receiving a socket address
-union sa *
-sa_alloc_getsockname(int socket);
+bool
+sa_prepare(union sa *address, socklen_t *len);
// # Get info about a socket address
@@ 108,19 118,4 @@ char const *
sa_str(union sa const *address);
-// # Wrap socket functions that use `sockaddr` structs
-
-inline int
-sa_bind(int socket, union sa const *address)
-{
- return bind(socket, &address->generic, sa_len(address));
-}
-
-inline int
-sa_connect(int socket, union sa const *address)
-{
- return connect(socket, &address->generic, sa_len(address));
-}
-
-
#endif
M src/sa/sa_tests.c => src/sa/sa_tests.c +376 -213
@@ 9,187 9,258 @@
static void
-test_sa_alloc(void)
+test_sa_unspec(void)
{
- union sa *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);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
- free(address);
+ bool success = sa_unspec(&address);
+
+ assert(success);
+ 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);
+}
+
+
+static void
+test_sa_unspec_for_null(void)
+{
+ bool success = sa_unspec(NULL);
+
+ assert(!success);
}
+
static void
-test_sa_alloc_from_in_addr_and_port(void)
+test_sa_from_in_addr_and_port(void)
{
- union sa *address = sa_alloc_from_in_addr_and_port(INADDR_LOOPBACK, 8080);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_in_addr_and_port(&address, INADDR_LOOPBACK, 8080);
+
+ assert(success);
+ 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)));
+}
+
- 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)));
+static void
+test_sa_from_in_addr_and_port_for_null(void)
+{
+ bool success = sa_from_in_addr_and_port(NULL, INADDR_LOOPBACK, 8080);
- free(address);
+ assert(!success);
}
static void
-test_sa_alloc_from_in6_addr_and_port(void)
+test_sa_from_in6_addr_and_port(void)
{
- union sa *address = sa_alloc_from_in6_addr_and_port(in6addr_loopback, 8080);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_in6_addr_and_port(&address, in6addr_loopback, 8080);
+
+ assert(success);
+ 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)));
+}
+
- 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)));
+static void
+test_sa_from_in6_addr_and_port_for_null(void)
+{
+ bool success = sa_from_in6_addr_and_port(NULL, in6addr_loopback, 8080);
- free(address);
+ assert(!success);
}
static void
-test_sa_alloc_from_ipv4_str_and_port(void)
+test_sa_from_ipv4_str_and_port(void)
{
- union sa *address = sa_alloc_from_ipv4_str_and_port("127.0.0.1", 8080);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
- 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)));
+ bool success = sa_from_ipv4_str_and_port(&address, "127.0.0.1", 8080);
- free(address);
+ assert(success);
+ 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)));
}
static void
-test_sa_alloc_from_ipv4_str_and_port_when_null(void)
+test_sa_from_ipv4_str_and_port_when_null(void)
{
- union sa *address = sa_alloc_from_ipv4_str_and_port(NULL, 8080);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_ipv4_str_and_port(NULL, "127.0.0.1", 8080);
- assert(!address);
+ assert(!success);
+
+ success = sa_from_ipv4_str_and_port(&address, NULL, 8080);
+
+ assert(!success);
}
static void
-test_sa_alloc_from_ipv4_str_and_port_when_invalid(void)
+test_sa_from_ipv4_str_and_port_when_invalid(void)
{
- union sa *address = sa_alloc_from_ipv4_str_and_port("invalid", 8080);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_ipv4_str_and_port(&address, "invalid", 8080);
- assert(!address);
+ assert(!success);
}
static void
-test_sa_alloc_from_ipv6_str_and_port(void)
+test_sa_from_ipv6_str_and_port(void)
{
- union sa *address = sa_alloc_from_ipv6_str_and_port("::1", 8080);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
- 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)));
+ bool success = sa_from_ipv6_str_and_port(&address, "::1", 8080);
- free(address);
+ assert(success);
+ 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)));
}
static void
-test_sa_alloc_from_ipv6_str_and_port_when_null(void)
+test_sa_from_ipv6_str_and_port_when_null(void)
{
- union sa *address = sa_alloc_from_ipv6_str_and_port(NULL, 8080);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
- assert(!address);
+ bool success = sa_from_ipv6_str_and_port(NULL, "::1", 8080);
+
+ assert(!success);
+
+ success = sa_from_ipv6_str_and_port(&address, NULL, 8080);
+
+ assert(!success);
}
static void
-test_sa_alloc_from_ipv6_str_and_port_when_invalid(void)
+test_sa_from_ipv6_str_and_port_when_invalid(void)
{
- union sa *address = sa_alloc_from_ipv6_str_and_port("invalid", 8080);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
- assert(!address);
+ bool success = sa_from_ipv6_str_and_port(NULL, "invalid", 8080);
+
+ assert(!success);
}
static void
-test_sa_alloc_from_path(void)
+test_sa_from_path(void)
{
- union sa *address = sa_alloc_from_path("/var/dood/http");
+ union sa address;
+ memset(&address, 0xff, sizeof address);
- assert(address);
- assert(AF_UNIX == address->generic.sa_family);
- assert(AF_UNIX == address->ipv4.sin_family);
- assert(AF_UNIX == address->ipv6.sin6_family);
- assert(AF_UNIX == address->local.sun_family);
- assert(AF_UNIX == address->storage.ss_family);
- assert(STR_EQ("/var/dood/http", address->local.sun_path));
- assert(STR_EQ("/var/dood/http", sa_str(address)));
+ bool success = sa_from_path(&address, "/var/dood/http");
- free(address);
+ assert(success);
+ assert(AF_UNIX == address.generic.sa_family);
+ assert(AF_UNIX == address.ipv4.sin_family);
+ assert(AF_UNIX == address.ipv6.sin6_family);
+ assert(AF_UNIX == address.local.sun_family);
+ assert(AF_UNIX == address.storage.ss_family);
+ assert(STR_EQ("/var/dood/http", address.local.sun_path));
+ assert(STR_EQ("/var/dood/http", sa_str(&address)));
}
static void
-test_sa_alloc_from_path_when_null(void)
+test_sa_from_path_when_null(void)
{
- union sa *address = sa_alloc_from_path(NULL);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_path(NULL, "/var/dood/http");
+
+ assert(!success);
- assert(!address);
+ success = sa_from_path(&address, NULL);
+
+ assert(!success);
}
static void
-test_sa_alloc_from_path_when_too_long(void)
+test_sa_from_path_when_too_long(void)
{
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
char const *too_long = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
assert(strlen(too_long) > UNIX_PATH_MAX);
- union sa *address = sa_alloc_from_path(too_long);
+ bool success = sa_from_path(&address, too_long);
- assert(!address);
+ assert(!success);
}
static void
-test_sa_alloc_from_sockaddr_for_unspecified(void)
+test_sa_from_sockaddr_for_unspecified(void)
{
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
struct sockaddr generic = {
.sa_family=AF_UNSPEC,
};
- union sa *address = sa_alloc_from_sockaddr(&generic);
+ bool success = sa_from_sockaddr(&address, &generic);
- assert(!address);
+ assert(!success);
}
static void
-test_sa_alloc_from_sockaddr_for_ipv4(void)
+test_sa_from_sockaddr_for_ipv4(void)
{
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
struct sockaddr_in ipv4 = {
.sin_family=AF_INET,
.sin_addr=(struct in_addr){
@@ 199,25 270,26 @@ test_sa_alloc_from_sockaddr_for_ipv4(void)
};
struct sockaddr *generic = (struct sockaddr *)&ipv4;
- union sa *address = sa_alloc_from_sockaddr(generic);
-
- 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)));
+ bool success = sa_from_sockaddr(&address, generic);
- free(address);
+ assert(success);
+ 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)));
}
static void
-test_sa_alloc_from_sockaddr_for_ipv6(void)
+test_sa_from_sockaddr_for_ipv6(void)
{
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
struct sockaddr_in6 ipv6 = {
.sin6_family=AF_INET6,
.sin6_addr=in6addr_loopback,
@@ 225,70 297,113 @@ test_sa_alloc_from_sockaddr_for_ipv6(void)
};
struct sockaddr *generic = (struct sockaddr *)&ipv6;
- union sa *address = sa_alloc_from_sockaddr(generic);
+ bool success = sa_from_sockaddr(&address, generic);
- 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);
+ assert(success);
+ 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)));
}
static void
-test_sa_alloc_from_sockaddr_for_local(void)
+test_sa_from_sockaddr_for_local(void)
{
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
struct sockaddr_un local = {
.sun_family = AF_UNIX,
.sun_path = "/var/dood/http",
};
struct sockaddr *generic = (struct sockaddr *)&local;
- union sa *address = sa_alloc_from_sockaddr(generic);
-
- assert(address);
- assert(AF_UNIX == address->generic.sa_family);
- assert(AF_UNIX == address->ipv4.sin_family);
- assert(AF_UNIX == address->ipv6.sin6_family);
- assert(AF_UNIX == address->local.sun_family);
- assert(AF_UNIX == address->storage.ss_family);
- assert(STR_EQ("/var/dood/http", address->local.sun_path));
- assert(STR_EQ("/var/dood/http", sa_str(address)));
+ bool success = sa_from_sockaddr(&address, generic);
- free(address);
+ assert(success);
+ assert(AF_UNIX == address.generic.sa_family);
+ assert(AF_UNIX == address.ipv4.sin_family);
+ assert(AF_UNIX == address.ipv6.sin6_family);
+ assert(AF_UNIX == address.local.sun_family);
+ assert(AF_UNIX == address.storage.ss_family);
+ assert(STR_EQ("/var/dood/http", address.local.sun_path));
+ assert(STR_EQ("/var/dood/http", sa_str(&address)));
}
static void
-test_sa_alloc_from_sockaddr_for_unsupported(void)
+test_sa_from_sockaddr_for_unsupported(void)
{
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
struct sockaddr generic = {
.sa_family=0xff,
};
- union sa *address = sa_alloc_from_sockaddr(&generic);
+ bool success = sa_from_sockaddr(&address, &generic);
- assert(!address);
+ assert(!success);
}
static void
-test_sa_alloc_from_sockaddr_when_null(void)
+test_sa_from_sockaddr_when_null(void)
{
- union sa *address = sa_alloc_from_sockaddr(NULL);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ struct sockaddr_in6 ipv6 = {
+ .sin6_family=AF_INET6,
+ .sin6_addr=in6addr_loopback,
+ .sin6_port=htons(8080),
+ };
+ struct sockaddr *generic = (struct sockaddr *)&ipv6;
+
+ bool success = sa_from_sockaddr(&address, NULL);
- assert(!address);
+ assert(!success);
+
+ success = sa_from_sockaddr(NULL, generic);
+
+ assert(!success);
+}
+
+
+static void
+test_sa_from_sockaddr_in(void)
+{
+ struct sockaddr_in ipv4 = {
+ .sin_family=AF_INET,
+ .sin_addr=(struct in_addr){
+ .s_addr=htonl(INADDR_LOOPBACK)
+ },
+ .sin_port=htons(8080),
+ };
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_sockaddr_in(&address, &ipv4);
+
+ assert(success);
+ 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)));
}
static void
-test_sa_alloc_from_sockaddr_in(void)
+test_sa_from_sockaddr_in_when_null(void)
{
struct sockaddr_in ipv4 = {
.sin_family=AF_INET,
@@ 297,95 412,137 @@ test_sa_alloc_from_sockaddr_in(void)
},
.sin_port=htons(8080),
};
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_sockaddr_in(NULL, &ipv4);
- union sa *address = sa_alloc_from_sockaddr_in(&ipv4);
+ assert(!success);
- 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)));
+ success = sa_from_sockaddr_in(&address, NULL);
- free(address);
+ assert(!success);
}
static void
-test_sa_alloc_from_sockaddr_in_when_null(void)
+test_sa_from_sockaddr_in6(void)
{
- union sa *address = sa_alloc_from_sockaddr_in(NULL);
+ struct sockaddr_in6 ipv6 = {
+ .sin6_family=AF_INET6,
+ .sin6_addr=in6addr_loopback,
+ .sin6_port=htons(8080),
+ };
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_sockaddr_in6(&address, &ipv6);
- assert(!address);
+ assert(success);
+ 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)));
}
static void
-test_sa_alloc_from_sockaddr_in6(void)
+test_sa_from_sockaddr_in6_when_null(void)
{
struct sockaddr_in6 ipv6 = {
.sin6_family=AF_INET6,
.sin6_addr=in6addr_loopback,
.sin6_port=htons(8080),
};
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_sockaddr_in6(NULL, &ipv6);
- union sa *address = sa_alloc_from_sockaddr_in6(&ipv6);
+ assert(!success);
- 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)));
+ success = sa_from_sockaddr_in6(&address, NULL);
- free(address);
+ assert(!success);
}
static void
-test_sa_alloc_from_sockaddr_in6_when_null(void)
+test_sa_from_sockaddr_un(void)
{
- union sa *address = sa_alloc_from_sockaddr_in6(NULL);
+ struct sockaddr_un local = {
+ .sun_family = AF_UNIX,
+ .sun_path = "/var/dood/http",
+ };
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_sockaddr_un(&address, &local);
- assert(!address);
+ assert(success);
+ assert(AF_UNIX == address.generic.sa_family);
+ assert(AF_UNIX == address.ipv4.sin_family);
+ assert(AF_UNIX == address.ipv6.sin6_family);
+ assert(AF_UNIX == address.local.sun_family);
+ assert(AF_UNIX == address.storage.ss_family);
+ assert(STR_EQ("/var/dood/http", address.local.sun_path));
+ assert(STR_EQ("/var/dood/http", sa_str(&address)));
}
static void
-test_sa_alloc_from_sockaddr_un(void)
+test_sa_from_sockaddr_un_when_null(void)
{
struct sockaddr_un local = {
.sun_family = AF_UNIX,
.sun_path = "/var/dood/http",
};
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+
+ bool success = sa_from_sockaddr_un(NULL, &local);
- union sa *address = sa_alloc_from_sockaddr_un(&local);
+ assert(!success);
- assert(address);
- assert(AF_UNIX == address->generic.sa_family);
- assert(AF_UNIX == address->ipv4.sin_family);
- assert(AF_UNIX == address->ipv6.sin6_family);
- assert(AF_UNIX == address->local.sun_family);
- assert(AF_UNIX == address->storage.ss_family);
- assert(STR_EQ("/var/dood/http", address->local.sun_path));
- assert(STR_EQ("/var/dood/http", sa_str(address)));
+ success = sa_from_sockaddr_un(&address, NULL);
- free(address);
+ assert(!success);
}
static void
-test_sa_alloc_from_sockaddr_un_when_null(void)
+test_sa_prepare(void)
{
- union sa *address = sa_alloc_from_sockaddr_un(NULL);
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+ socklen_t len = 0xffff;
- assert(!address);
+ bool success = sa_prepare(&address, &len);
+
+ assert(success);
+ assert(AF_UNSPEC == address.generic.sa_family);
+ assert(sizeof(struct sockaddr_storage) == len);
+}
+
+
+static void
+test_sa_prepare_for_null(void)
+{
+ union sa address;
+ memset(&address, 0xff, sizeof address);
+ socklen_t len = 0xffff;
+
+ bool success = sa_prepare(NULL, &len);
+
+ assert(!success);
+
+ success = sa_prepare(&address, NULL);
+
+ assert(!success);
}
@@ 405,33 562,30 @@ test_sa_len_for_unspecified(void)
static void
test_sa_len_for_ipv4(void)
{
- union sa *address = sa_alloc_from_in_addr_and_port(INADDR_LOOPBACK, 8080);
-
- assert(sizeof(struct sockaddr_in) == sa_len(address));
+ union sa address;
+ sa_from_in_addr_and_port(&address, INADDR_LOOPBACK, 8080);
- free(address);
+ assert(sizeof(struct sockaddr_in) == sa_len(&address));
}
static void
test_sa_len_for_ipv6(void)
{
- union sa *address = sa_alloc_from_in6_addr_and_port(in6addr_loopback, 8080);
-
- assert(sizeof(struct sockaddr_in6) == sa_len(address));
+ union sa address;
+ sa_from_in6_addr_and_port(&address, in6addr_loopback, 8080);
- free(address);
+ assert(sizeof(struct sockaddr_in6) == sa_len(&address));
}
static void
test_sa_len_for_local(void)
{
- union sa *address = sa_alloc_from_path("/var/dood/http");
+ union sa address;
+ sa_from_path(&address, "/var/dood/http");
- assert(sizeof(struct sockaddr_un) == sa_len(address));
-
- free(address);
+ assert(sizeof(struct sockaddr_un) == sa_len(&address));
}
@@ 491,36 645,45 @@ test_sa_str_for_null(void)
int
main(int argc, char *argv[])
{
- test_sa_alloc();
+ test_sa_unspec();
+ test_sa_unspec_for_null();
+
+ test_sa_from_in_addr_and_port();
+ test_sa_from_in_addr_and_port_for_null();
+
+ test_sa_from_in6_addr_and_port();
+ test_sa_from_in6_addr_and_port_for_null();
+
+ test_sa_from_ipv4_str_and_port();
+ test_sa_from_ipv4_str_and_port_when_null();
+ test_sa_from_ipv4_str_and_port_when_invalid();
+
+ test_sa_from_ipv6_str_and_port();
+ test_sa_from_ipv6_str_and_port_when_null();
+ test_sa_from_ipv6_str_and_port_when_invalid();
- test_sa_alloc_from_in_addr_and_port();
- test_sa_alloc_from_in6_addr_and_port();
+ test_sa_from_path();
+ test_sa_from_path_when_null();
+ test_sa_from_path_when_too_long();
- test_sa_alloc_from_ipv4_str_and_port();
- test_sa_alloc_from_ipv4_str_and_port_when_null();
- test_sa_alloc_from_ipv4_str_and_port_when_invalid();
+ test_sa_from_sockaddr_for_unspecified();
+ test_sa_from_sockaddr_for_ipv4();
+ test_sa_from_sockaddr_for_ipv6();
+ test_sa_from_sockaddr_for_local();
+ test_sa_from_sockaddr_for_unsupported();
+ test_sa_from_sockaddr_when_null();
- test_sa_alloc_from_ipv6_str_and_port();
- test_sa_alloc_from_ipv6_str_and_port_when_null();
- test_sa_alloc_from_ipv6_str_and_port_when_invalid();
+ test_sa_from_sockaddr_in();
+ test_sa_from_sockaddr_in_when_null();
- test_sa_alloc_from_path();
- test_sa_alloc_from_path_when_null();
- test_sa_alloc_from_path_when_too_long();
+ test_sa_from_sockaddr_in6();
+ test_sa_from_sockaddr_in6_when_null();
- test_sa_alloc_from_sockaddr_for_unspecified();
- test_sa_alloc_from_sockaddr_for_ipv4();
- test_sa_alloc_from_sockaddr_for_ipv6();
- test_sa_alloc_from_sockaddr_for_local();
- test_sa_alloc_from_sockaddr_for_unsupported();
- test_sa_alloc_from_sockaddr_when_null();
+ test_sa_from_sockaddr_un();
+ test_sa_from_sockaddr_un_when_null();
- test_sa_alloc_from_sockaddr_in();
- test_sa_alloc_from_sockaddr_in_when_null();
- test_sa_alloc_from_sockaddr_in6();
- test_sa_alloc_from_sockaddr_in6_when_null();
- test_sa_alloc_from_sockaddr_un();
- test_sa_alloc_from_sockaddr_un_when_null();
+ test_sa_prepare();
+ test_sa_prepare_for_null();
test_sa_len_for_unspecified();
test_sa_len_for_ipv4();