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();