M src/sa/sa.c => src/sa/sa.c +28 -29
@@ 19,6 19,32 @@ sa_alloc_from_ipv4_address_and_port(in_addr_t in_addr, in_port_t in_port)
union sa_address *
+sa_alloc_from_ipv6_address_and_port(struct in6_addr in6_addr, in_port_t in_port)
+{
+ struct sockaddr_in6 inet6 = {
+ .sin6_family=AF_INET6,
+ .sin6_addr=in6_addr,
+ .sin6_port=htons(in_port),
+ };
+ return sa_alloc_from_sockaddr_in6(&inet6);
+}
+
+
+union sa_address *
+sa_alloc_from_unix_path(char const *path)
+{
+ if (!path) return NULL;
+ if (strlen(path) >= UNIX_PATH_MAX) return NULL;
+
+ struct sockaddr_un local_address = {
+ .sun_family = AF_UNIX,
+ };
+ strcpy(local_address.sun_path, path);
+ return sa_alloc_from_sockaddr_un(&local_address);
+}
+
+
+union sa_address *
sa_alloc_from_sockaddr_in(struct sockaddr_in const *ipv4_address)
{
union sa_address *address = calloc(1, sizeof(union sa_address));
@@ 35,7 61,7 @@ sa_alloc_from_sockaddr_in(struct sockaddr_in const *ipv4_address)
return address;
-fail:
+ fail:
free(address);
return NULL;
@@ 43,18 69,6 @@ fail:
union sa_address *
-sa_alloc_from_ipv6_address_and_port(struct in6_addr in6_addr, in_port_t in_port)
-{
- struct sockaddr_in6 inet6 = {
- .sin6_family=AF_INET6,
- .sin6_addr=in6_addr,
- .sin6_port=htons(in_port),
- };
- return sa_alloc_from_sockaddr_in6(&inet6);
-}
-
-
-union sa_address *
sa_alloc_from_sockaddr_in6(struct sockaddr_in6 const *ipv6_address)
{
union sa_address *address = calloc(1, sizeof(union sa_address));
@@ 72,27 86,13 @@ sa_alloc_from_sockaddr_in6(struct sockaddr_in6 const *ipv6_address)
return address;
-fail:
+ fail:
free(address);
return NULL;
}
union sa_address *
-sa_alloc_from_path(char const *path)
-{
- if (!path) return NULL;
- if (strlen(path) >= UNIX_PATH_MAX) return NULL;
-
- struct sockaddr_un local_address = {
- .sun_family = AF_UNIX,
- };
- strcpy(local_address.sun_path, path);
- return sa_alloc_from_sockaddr_un(&local_address);
-}
-
-
-union sa_address *
sa_alloc_from_sockaddr_un(struct sockaddr_un const *local_address)
{
union sa_address *address = calloc(1, sizeof(union sa_address));
@@ 114,7 114,6 @@ sa_len(union sa_address const *address)
case AF_INET6: return sizeof(struct sockaddr_in6);
default: return sizeof(struct sockaddr_storage);
}
- return 0;
}
M src/sa/sa.h => src/sa/sa.h +24 -11
@@ 8,13 8,12 @@
/* Size of fixed string buffers for IPv4 and IPv6 string representations,
- * including port. Note that `SA_PORT_STR_LEN` and `SA_COLON_STR_LEN` _do not_
- * include space for a nul terminator, but `INET_ADDRSTRLEN` and
- * `INET6_ADDRSTRLEN`, defined by
- * [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html)
- * _do_ include space for a nul terminator and thus so do `SA_IPV4_STR_SIZE`
- * and `SA_IPV6_STR_SIZE`.
- */
+ including port. Note that `SA_PORT_STR_LEN` and `SA_COLON_STR_LEN` _do not_
+ include space for a nul terminator, but `INET_ADDRSTRLEN` and
+ `INET6_ADDRSTRLEN`, defined by
+ [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html)
+ _do_ include space for a nul terminator and thus so do `SA_IPV4_STR_SIZE`
+ and `SA_IPV6_STR_SIZE`. */
#define SA_PORT_STR_LEN 5
#define SA_COLON_STR_LEN 1
#define SA_IPV4_STR_SIZE (INET_ADDRSTRLEN + SA_COLON_STR_LEN + SA_PORT_STR_LEN)
@@ 25,6 24,10 @@
#endif
+/* The `sa_address` union holds storage for each of the `sockaddr`
+ [type puns](https://en.wikipedia.org/wiki/Type_punning) along with space for
+ a string representation. For the `sockaddr_un` address type, the `sun_path`
+ field is used as the string representation. */
union sa_address {
struct sockaddr generic;
struct {
@@ 40,24 43,32 @@ union sa_address {
};
+// # Allocate socket address from components
+
union sa_address *
sa_alloc_from_ipv4_address_and_port(in_addr_t in_addr, in_port_t in_port);
union sa_address *
-sa_alloc_from_sockaddr_in(struct sockaddr_in const *ipv4_address);
+sa_alloc_from_ipv6_address_and_port(struct in6_addr in6_addr, in_port_t in_port);
union sa_address *
-sa_alloc_from_ipv6_address_and_port(struct in6_addr in6_addr, in_port_t in_port);
+sa_alloc_from_unix_path(char const *path);
+
+
+// # Allocate socket address from a `sockaddr`-type struct.
union sa_address *
-sa_alloc_from_sockaddr_in6(struct sockaddr_in6 const *ipv6_address);
+sa_alloc_from_sockaddr_in(struct sockaddr_in const *ipv4_address);
union sa_address *
-sa_alloc_from_path(char const *path);
+sa_alloc_from_sockaddr_in6(struct sockaddr_in6 const *ipv6_address);
union sa_address *
sa_alloc_from_sockaddr_un(struct sockaddr_un const *local_address);
+
+// # Get info about a socket address
+
socklen_t
sa_len(union sa_address const *address);
@@ 65,6 76,8 @@ char const *
sa_str(union sa_address const *address);
+// # Wrap socket functions that use `sockaddr` structs
+
inline int
sa_bind(int socket, union sa_address const *address)
{
M src/sa/sa_tests.c => src/sa/sa_tests.c +61 -62
@@ 28,33 28,6 @@ test_sa_alloc_from_ipv4_address_and_port(void)
static void
-test_sa_alloc_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 *address = sa_alloc_from_sockaddr_in(&ipv4);
-
- 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_address_and_port(void)
{
union sa_address *address = sa_alloc_from_ipv6_address_and_port(in6addr_loopback, 8080);
@@ 74,34 47,9 @@ test_sa_alloc_from_ipv6_address_and_port(void)
static void
-test_sa_alloc_from_sockaddr_in6(void)
-{
- struct sockaddr_in6 ipv6 = {
- .sin6_family=AF_INET6,
- .sin6_addr=in6addr_loopback,
- .sin6_port=htons(8080),
- };
-
- union sa_address *address = sa_alloc_from_sockaddr_in6(&ipv6);
-
- 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)
+test_sa_alloc_from_unix_path(void)
{
- union sa_address *address = sa_alloc_from_path("/var/dood/http");
+ union sa_address *address = sa_alloc_from_unix_path("/var/dood/http");
assert(address);
assert(AF_UNIX == address->generic.sa_family);
@@ 119,7 67,7 @@ test_sa_alloc_from_path(void)
static void
test_sa_alloc_from_path_when_null(void)
{
- union sa_address *address = sa_alloc_from_path(NULL);
+ union sa_address *address = sa_alloc_from_unix_path(NULL);
assert(!address);
}
@@ 131,13 79,65 @@ test_sa_alloc_from_path_when_too_long(void)
char const *too_long = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
assert(strlen(too_long) > UNIX_PATH_MAX);
- union sa_address *address = sa_alloc_from_path(too_long);
+ union sa_address *address = sa_alloc_from_unix_path(too_long);
assert(!address);
}
static void
+test_sa_alloc_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 *address = sa_alloc_from_sockaddr_in(&ipv4);
+
+ 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_sockaddr_in6(void)
+{
+ struct sockaddr_in6 ipv6 = {
+ .sin6_family=AF_INET6,
+ .sin6_addr=in6addr_loopback,
+ .sin6_port=htons(8080),
+ };
+
+ union sa_address *address = sa_alloc_from_sockaddr_in6(&ipv6);
+
+ 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_sockaddr_un(void)
{
struct sockaddr_un local = {
@@ 198,7 198,7 @@ test_sa_len_for_ipv6(void)
static void
test_sa_len_for_unix(void)
{
- union sa_address *address = sa_alloc_from_path("/var/dood/http");
+ union sa_address *address = sa_alloc_from_unix_path("/var/dood/http");
assert(sizeof(struct sockaddr_un) == sa_len(address));
@@ 249,14 249,13 @@ int
main(int argc, char *argv[])
{
test_sa_alloc_from_ipv4_address_and_port();
- test_sa_alloc_from_sockaddr_in();
-
test_sa_alloc_from_ipv6_address_and_port();
- test_sa_alloc_from_sockaddr_in6();
-
- test_sa_alloc_from_path();
+ test_sa_alloc_from_unix_path();
test_sa_alloc_from_path_when_null();
test_sa_alloc_from_path_when_too_long();
+
+ test_sa_alloc_from_sockaddr_in();
+ test_sa_alloc_from_sockaddr_in6();
test_sa_alloc_from_sockaddr_un();
test_sa_len_for_unspecified();