From 4aa122edce34eb4a400bc0cba435ebe270f7000c Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 18 Apr 2014 13:07:52 +1000 Subject: [PATCH] Add helper function for opening unix client sockets and cleanly closing and unlinking unix server sockets --- configure.ac | 2 +- src/libckpool.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++-- src/libckpool.h | 2 ++ 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 00ae505d..33afd572 100644 --- a/configure.ac +++ b/configure.ac @@ -38,7 +38,7 @@ AC_CHECK_HEADERS(stdio.h stdlib.h fcntl.h sys/time.h unistd.h) AC_CHECK_HEADERS(ctype.h errno.h byteswap.h string.h time.h) AC_CHECK_HEADERS(endian.h sys/endian.h arpa/inet.h syslog.h) AC_CHECK_HEADERS(alloca.h pthread.h stdio.h math.h) -AC_CHECK_HEADERS(sys/types.h sys/socket.h linux/un.h netdb.h) +AC_CHECK_HEADERS(sys/types.h sys/socket.h sys/stat.h linux/un.h netdb.h) AC_CHECK_HEADERS(stdint.h netinet/in.h netinet/tcp.h) AC_CHECK_HEADERS(jansson.h) diff --git a/src/libckpool.c b/src/libckpool.c index b8400a0d..c60762b4 100644 --- a/src/libckpool.c +++ b/src/libckpool.c @@ -16,6 +16,7 @@ #else #include #endif +#include #include #include #include @@ -500,10 +501,23 @@ void empty_socket(int fd) } while (ret > 0); } +void close_unix_socket(const int sockd, const char *server_path) +{ + int ret; + + ret = close(sockd); + if (unlikely(ret < 0)) + LOGERR("Failed to close sock %d %s", sockd, server_path); + ret = unlink(server_path); + if (unlikely(ret < 0)) + LOGERR("Failed to unlink %s", server_path); +} + int open_unix_server(const char *server_path) { struct sockaddr_un serveraddr; int sockd = -1, len, ret; + struct stat buf; if (likely(server_path)) { len = strlen(server_path); @@ -516,6 +530,21 @@ int open_unix_server(const char *server_path) goto out; } + if (!stat(server_path, &buf)) { + if ((buf.st_mode & S_IFMT) == S_IFSOCK) { + ret = unlink(server_path); + if (ret) { + LOGERR("Unlink of %s failed in open_unix_server", server_path); + goto out; + } + LOGDEBUG("Unlinked %s to recreate socket", server_path); + } else { + LOGWARNING("%s already exists and is not a socket, not removing", + server_path); + goto out; + } + } + sockd = socket(AF_UNIX, SOCK_STREAM, 0); if (unlikely(sockd < 0)) { LOGERR("Failed to open socket in open_unix_server"); @@ -528,7 +557,7 @@ int open_unix_server(const char *server_path) ret = bind(sockd, (struct sockaddr *)&serveraddr, sizeof(&serveraddr)); if (unlikely(ret < 0)) { LOGERR("Failed to bind to socket in open_unix_server"); - close(sockd); + close_unix_socket(sockd, server_path); sockd = -1; goto out; } @@ -536,7 +565,7 @@ int open_unix_server(const char *server_path) ret = listen(sockd, 1); if (unlikely(ret < 0)) { LOGERR("Failed to listen to socket in open_unix_server"); - close(sockd); + close_unix_socket(sockd, server_path); sockd = -1; goto out; } @@ -546,6 +575,41 @@ out: return sockd; } +int open_unix_client(const char *server_path) +{ + struct sockaddr_un serveraddr; + int sockd = -1, len, ret; + + if (likely(server_path)) { + len = strlen(server_path); + if (unlikely(len < 1 || len > UNIX_PATH_MAX)) { + LOGERR("Invalid server path length %d in open_unix_client", len); + goto out; + } + } else { + LOGERR("Null passed as server_path to open_unix_client"); + goto out; + } + + sockd = socket(AF_UNIX, SOCK_STREAM, 0); + if (unlikely(sockd < 0)) { + LOGERR("Failed to open socket in open_unix_client"); + goto out; + } + memset(&serveraddr, 0, sizeof(serveraddr)); + serveraddr.sun_family = AF_UNIX; + strcpy(serveraddr.sun_path, server_path); + + ret = connect(sockd, (struct sockaddr *)&serveraddr, sizeof(&serveraddr)); + if (unlikely(ret < 0)) { + LOGERR("Failed to bind to socket in open_unix_client"); + close(sockd); + sockd = -1; + goto out; + } +out: + return sockd; +} json_t *json_rpc_call(connsock_t *cs, const char *rpc_req) { diff --git a/src/libckpool.h b/src/libckpool.h index 380f279a..4c57188b 100644 --- a/src/libckpool.h +++ b/src/libckpool.h @@ -186,7 +186,9 @@ int connect_socket(char *url, char *port); int write_socket(int fd, const void *buf, size_t nbyte); int read_socket_line(connsock_t *cs); void empty_socket(int fd); +void close_unix_socket(const int sockd, const char *server_path); int open_unix_server(const char *server_path); +int open_unix_client(const char *server_path); json_t *json_rpc_call(connsock_t *cs, const char *rpc_req);