X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Ffrontend%2Fsock.c;h=96bc04baf805640b747f46861d181ec0177e4e4b;hp=aa7cab068b115d07d2008eceb78347b99c5c19cd;hb=f78d30d42f9fe3b58f1c2132cafe4c8687b8bd46;hpb=7eae8c92fd40a050f9ce4a7132191fbcef810dc0 diff --git a/src/frontend/sock.c b/src/frontend/sock.c index aa7cab0..96bc04b 100644 --- a/src/frontend/sock.c +++ b/src/frontend/sock.c @@ -25,6 +25,10 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + #include "sysdb.h" #include "core/object.h" #include "frontend/connection-private.h" @@ -33,6 +37,7 @@ #include "utils/channel.h" #include "utils/error.h" #include "utils/llist.h" +#include "utils/os.h" #include "utils/strbuf.h" #include @@ -50,6 +55,8 @@ #include #include +#include + #include /* @@ -89,6 +96,9 @@ struct sdb_fe_socket { static int open_unix_sock(listener_t *listener) { + const char *addr; + char *addr_copy; + char *base_dir; struct sockaddr_un sa; int status; @@ -100,12 +110,35 @@ open_unix_sock(listener_t *listener) return -1; } + if (*listener->address == '/') + addr = listener->address; + else + addr = listener->address + strlen("unix:"); + memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; - strncpy(sa.sun_path, listener->address + strlen("unix:"), - sizeof(sa.sun_path)); + strncpy(sa.sun_path, addr, sizeof(sa.sun_path)); + + addr_copy = strdup(addr); + if (! addr_copy) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "frontend: strdup failed: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + base_dir = dirname(addr_copy); + + /* ensure that the directory exists */ + if (sdb_mkdir_all(base_dir, 0777)) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "frontend: Failed to create directory '%s': %s", + base_dir, sdb_strerror(errno, errbuf, sizeof(errbuf))); + free(addr_copy); + return -1; + } + free(addr_copy); - if (unlink(listener->address + strlen("unix:")) && (errno != ENOENT)) { + if (unlink(addr) && (errno != ENOENT)) { char errbuf[1024]; sdb_log(SDB_LOG_WARNING, "frontend: Failed to remove stale UNIX " "socket %s: %s", listener->address + strlen("unix:"), @@ -125,15 +158,22 @@ open_unix_sock(listener_t *listener) static void close_unix_sock(listener_t *listener) { + const char *addr; assert(listener); + if (! listener->address) return; + if (*listener->address == '/') + addr = listener->address; + else + addr = listener->address + strlen("unix:"); + if (listener->sock_fd >= 0) close(listener->sock_fd); listener->sock_fd = -1; - unlink(listener->address + strlen("unix:")); + unlink(addr); } /* close_unix_sock */ /* @@ -143,7 +183,7 @@ close_unix_sock(listener_t *listener) /* the enum has to be sorted the same as the implementations array * to ensure that the type may be used as index into the array */ enum { - LISTENER_UNIXSOCK = 0, + LISTENER_UNIXSOCK = 0, /* this is the default */ }; static fe_listener_impl_t listener_impls[] = { { LISTENER_UNIXSOCK, "unix", open_unix_sock, close_unix_sock }, @@ -195,7 +235,7 @@ get_type(const char *address) sep = strchr(address, (int)':'); if (! sep) - return -1; + return listener_impls[0].type; assert(sep > address); len = (size_t)(sep - address); @@ -270,6 +310,20 @@ listener_create(sdb_fe_socket_t *sock, const char *address) return listener; } /* listener_create */ +static void +socket_clear(sdb_fe_socket_t *sock) +{ + size_t i; + + assert(sock); + for (i = 0; i < sock->listeners_num; ++i) + listener_destroy(sock->listeners + i); + if (sock->listeners) + free(sock->listeners); + sock->listeners = NULL; + sock->listeners_num = 0; +} /* socket_clear */ + static void socket_close(sdb_fe_socket_t *sock) { @@ -377,9 +431,14 @@ socket_handle_incoming(sdb_fe_socket_t *sock, while (sdb_llist_iter_has_next(iter)) { sdb_object_t *obj = sdb_llist_iter_get_next(iter); - if (FD_ISSET(CONN(obj)->fd, exceptions)) + if (FD_ISSET(CONN(obj)->fd, exceptions)) { sdb_log(SDB_LOG_INFO, "Exception on fd %d", CONN(obj)->fd); + /* close the connection */ + sdb_llist_iter_remove_current(iter); + sdb_object_deref(obj); + continue; + } if (FD_ISSET(CONN(obj)->fd, ready)) { sdb_llist_iter_remove_current(iter); @@ -414,17 +473,10 @@ sdb_fe_sock_create(void) void sdb_fe_sock_destroy(sdb_fe_socket_t *sock) { - size_t i; - if (! sock) return; - for (i = 0; i < sock->listeners_num; ++i) { - listener_destroy(sock->listeners + i); - } - if (sock->listeners) - free(sock->listeners); - sock->listeners = NULL; + socket_clear(sock); sdb_llist_destroy(sock->open_connections); sock->open_connections = NULL; @@ -445,6 +497,15 @@ sdb_fe_sock_add_listener(sdb_fe_socket_t *sock, const char *address) return 0; } /* sdb_fe_sock_add_listener */ +void +sdb_fe_sock_clear_listeners(sdb_fe_socket_t *sock) +{ + if (! sock) + return; + + socket_clear(sock); +} /* sdb_fe_sock_clear_listeners */ + int sdb_fe_sock_listen_and_serve(sdb_fe_socket_t *sock, sdb_fe_loop_t *loop) { @@ -482,8 +543,8 @@ sdb_fe_sock_listen_and_serve(sdb_fe_socket_t *sock, sdb_fe_loop_t *loop) return -1; } - sdb_log(SDB_LOG_INFO, "frontend: Starting %d connection " - "handler thread%s managing %d listener%s", + sdb_log(SDB_LOG_INFO, "frontend: Starting %zu connection " + "handler thread%s managing %zu listener%s", loop->num_threads, loop->num_threads == 1 ? "" : "s", sock->listeners_num, sock->listeners_num == 1 ? "" : "s"); @@ -525,6 +586,13 @@ sdb_fe_sock_listen_and_serve(sdb_fe_socket_t *sock, sdb_fe_loop_t *loop) while (sdb_llist_iter_has_next(iter)) { sdb_object_t *obj = sdb_llist_iter_get_next(iter); + + if (CONN(obj)->fd < 0) { + sdb_llist_iter_remove_current(iter); + sdb_object_deref(obj); + continue; + } + FD_SET(CONN(obj)->fd, &ready); FD_SET(CONN(obj)->fd, &exceptions);