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