Просмотр исходного кода

qdevice: Add preliminary version of IPC

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Jan Friesse 10 лет назад
Родитель
Сommit
415436a105

+ 3 - 1
qdevices/Makefile.am

@@ -53,7 +53,9 @@ corosync_qdevice_SOURCES	= corosync-qdevice.c qdevice-cmap.c qdevice-instance.c
 				  qdevice-model.c \
 				  qdevice-model-net.c \
 				  qdevice-net-instance.c dynar.c send-buffer-list.c timer-list.c \
-				  msg.c msgio.c nss-sock.c tlv.c unix-socket.c qdevice-local-socket.c \
+				  msg.c msgio.c nss-sock.c tlv.c \
+				  unix-socket.c unix-socket-client.c unix-socket-client-list.c \
+				  unix-socket-ipc.c qdevice-ipc.c \
 				  qdevice-net-poll.c qdevice-net-send.c qdevice-net-votequorum.c \
 				  qdevice-net-socket.c qdevice-net-nss.c qdevice-net-msg-received.c \
 				  qdevice-net-cast-vote-timer.c qdevice-net-echo-request-timer.c \

+ 8 - 6
qdevices/corosync-qdevice.c

@@ -36,10 +36,10 @@
 
 #include "qdevice-config.h"
 #include "qdevice-cmap.h"
+#include "qdevice-ipc.h"
 #include "qdevice-log.h"
 #include "qdevice-model.h"
 #include "qdevice-votequorum.h"
-#include "qdevice-local-socket.h"
 #include "utils.h"
 
 struct qdevice_instance *global_instance;
@@ -48,14 +48,14 @@ static void
 signal_int_handler(int sig)
 {
 	qdevice_log(LOG_DEBUG, "SIGINT received - closing local unix socket");
-	qdevice_local_socket_destroy(global_instance);
+	qdevice_ipc_destroy(global_instance);
 }
 
 static void
 signal_term_handler(int sig)
 {
 	qdevice_log(LOG_DEBUG, "SIGTERM received - closing server socket");
-	qdevice_local_socket_destroy(global_instance);
+	qdevice_ipc_destroy(global_instance);
 }
 
 static void
@@ -120,7 +120,6 @@ main(int argc, char * const argv[])
 	cli_parse(argc, argv, &foreground, &force_debug);
 
 	qdevice_instance_init(&instance);
-	global_instance = &instance;
 
 	qdevice_cmap_init(&instance);
 	qdevice_log_init(&instance, force_debug);
@@ -146,10 +145,12 @@ main(int argc, char * const argv[])
 	qdevice_votequorum_init(&instance);
 
 	qdevice_log(LOG_DEBUG, "Initializing local socket");
-	if (qdevice_local_socket_init(&instance) != 0) {
+	if (qdevice_ipc_init(&instance) != 0) {
 		return (1);
 	}
 
+	global_instance = &instance;
+
 	signal_handlers_register();
 
 	qdevice_log(LOG_DEBUG, "Registering qdevice models");
@@ -188,7 +189,8 @@ main(int argc, char * const argv[])
 	qdevice_log(LOG_DEBUG, "Destorying qdevice model");
 	qdevice_model_destroy(&instance);
 
-	qdevice_local_socket_destroy(&instance);
+	qdevice_ipc_destroy(&instance);
+
 	qdevice_votequorum_destroy(&instance);
 	qdevice_cmap_destroy(&instance);
 	qdevice_log_close(&instance);

+ 6 - 0
qdevices/qdevice-config.h

@@ -68,6 +68,12 @@ extern "C" {
 
 #define QDEVICE_VOTEQUORUM_DEVICE_NAME      "Qdevice"
 
+#define QDEVICE_ENABLE_NSS			1
+
+#define QDEVICE_IPC_MAX_CLIENTS			10
+#define QDEVICE_IPC_MAX_RECEIVE_SIZE		(4*1024)
+#define QDEVICE_IPC_MAX_SEND_SIZE		(64*1024)
+
 #ifdef __cplusplus
 }
 #endif

+ 2 - 1
qdevices/qdevice-instance.h

@@ -45,6 +45,7 @@
 
 #include "qdevice-model-type.h"
 #include "node-list.h"
+#include "unix-socket-ipc.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -61,7 +62,7 @@ struct qdevice_instance {
 	votequorum_handle_t votequorum_handle;
 	int votequorum_poll_fd;
 
-	int local_socket_fd;
+	struct unix_socket_ipc local_ipc;
 
 	enum qdevice_model_type model_type;
 

+ 94 - 0
qdevices/qdevice-ipc.c

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qdevice-config.h"
+#include "qdevice-ipc.h"
+#include "qdevice-log.h"
+#include "unix-socket-ipc.h"
+
+int
+qdevice_ipc_init(struct qdevice_instance *instance)
+{
+	if (unix_socket_ipc_init(&instance->local_ipc, QDEVICE_LOCAL_SOCKET_FILE,
+	    QDEVICE_LOCAL_SOCKET_BACKLOG, QDEVICE_IPC_MAX_CLIENTS, QDEVICE_IPC_MAX_RECEIVE_SIZE,
+	    QDEVICE_IPC_MAX_SEND_SIZE) != 0) {
+		qdevice_log_err(LOG_ERR, "Can't create unix socket");
+
+		return (-1);
+	}
+
+	return (0);
+}
+
+int
+qdevice_ipc_destroy(struct qdevice_instance *instance)
+{
+	int res;
+
+	res = unix_socket_ipc_destroy(&instance->local_ipc);
+	if (res != 0) {
+		qdevice_log_err(LOG_WARNING, "Can't destroy local IPC");
+	}
+
+	return (res);
+}
+
+int
+qdevice_ipc_accept(struct qdevice_instance *instance, struct unix_socket_client **res_client)
+{
+	int res;
+	int accept_res;
+
+	accept_res = unix_socket_ipc_accept(&instance->local_ipc, res_client);
+
+	switch (accept_res) {
+	case -1:
+		qdevice_log_err(LOG_ERR, "Can't accept local IPC connection");
+		res = -1;
+		break;
+	case -2:
+		qdevice_log(LOG_ERR, "Maximum IPC clients reached. Not accepting connection");
+		res = -1;
+		break;
+	case -3:
+		qdevice_log(LOG_ERR, "Can't add client to list");
+		res = -1;
+		break;
+	default:
+		res = 0;
+		break;
+	}
+
+	return (res);
+}

+ 7 - 7
qdevices/qdevice-local-socket.h → qdevices/qdevice-ipc.h

@@ -32,8 +32,8 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef _QDEVICE_LOCAL_SOCKET_H_
-#define _QDEVICE_LOCAL_SOCKET_H_
+#ifndef _QDEVICE_IPC_H_
+#define _QDEVICE_IPC_H_
 
 #include "qdevice-instance.h"
 
@@ -41,15 +41,15 @@
 extern "C" {
 #endif
 
-struct qdevice_local_socket {
-};
+extern int		qdevice_ipc_init(struct qdevice_instance *instance);
 
-extern int		qdevice_local_socket_init(struct qdevice_instance *instance);
+extern int		qdevice_ipc_destroy(struct qdevice_instance *instance);
 
-extern void		qdevice_local_socket_destroy(struct qdevice_instance *instance);
+extern int		qdevice_ipc_accept(struct qdevice_instance *instance,
+    struct unix_socket_client **res_client);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* _QDEVICE_LOCAL_SOCKET_H_ */
+#endif /* _QDEVICE_IPC_H_ */

+ 1 - 1
qdevices/qdevice-net-instance.c

@@ -347,7 +347,7 @@ qdevice_net_instance_init_from_cmap(struct qdevice_instance *instance)
 	    host_addr, host_port, cluster_name, &tie_breaker, connect_timeout,
 	    force_ip_version,
 	    instance->cmap_poll_fd, instance->votequorum_poll_fd,
-	    instance->local_socket_fd) == -1) {
+	    instance->local_ipc.socket) == -1) {
 		qdevice_log(LOG_ERR, "Can't initialize qdevice-net instance");
 		goto error_free_instance;
 	}

+ 20 - 1
qdevices/qdevice-net-poll.c

@@ -38,6 +38,12 @@
 #include "qdevice-net-send.h"
 #include "qdevice-net-socket.h"
 #include "qdevice-votequorum.h"
+#include "qdevice-ipc.h"
+
+/*
+ * Needed for creating nspr handle from unix fd
+ */
+#include <private/pprio.h>
 
 enum qdevice_net_poll_pfd {
 	QDEVICE_NET_POLL_VOTEQUORUM,
@@ -146,8 +152,21 @@ qdevice_net_poll_err_socket(struct qdevice_net_instance *instance, const PRPollD
 static void
 qdevice_net_poll_read_local_socket(struct qdevice_net_instance *instance)
 {
+	struct unix_socket_client *client;
+	PRFileDesc *prfd;
+
+	if (qdevice_ipc_accept(instance->qdevice_instance_ptr, &client) != 0) {
+		return ;
+	}
+
+	prfd = PR_CreateSocketPollFd(client->socket);
+	if (prfd == NULL) {
+		qdevice_log_nss(LOG_CRIT, "Can't create NSPR poll fd for IPC client");
+
+		return ;
+	}
 
-//	qdevice_log(LOG_DEBUG, "READ ON LOCAL SOCKET");
+	client->user_data = (void *)prfd;
 }
 
 int

+ 2 - 0
qdevices/qnetd-client-list.c

@@ -79,6 +79,7 @@ qnetd_client_list_free(struct qnetd_client_list *client_list)
 	while (client != NULL) {
 		client_next = TAILQ_NEXT(client, entries);
 
+		qnetd_client_destroy(client);
 		free(client);
 
 		client = client_next;
@@ -92,6 +93,7 @@ qnetd_client_list_del(struct qnetd_client_list *client_list, struct qnetd_client
 {
 
 	TAILQ_REMOVE(client_list, client, entries);
+
 	qnetd_client_destroy(client);
 	free(client);
 }

+ 0 - 1
qdevices/qnetd-instance.c

@@ -77,7 +77,6 @@ qnetd_instance_destroy(struct qnetd_instance *instance)
 	struct qnetd_client *client;
 	struct qnetd_client *client_next;
 
-
 	qnetd_dpd_timer_destroy(instance);
 
 	client = TAILQ_FIRST(&instance->clients);

+ 108 - 0
qdevices/unix-socket-client-list.c

@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unix-socket-client-list.h"
+
+void
+unix_socket_client_list_init(struct unix_socket_client_list *client_list)
+{
+
+	TAILQ_INIT(client_list);
+}
+
+struct unix_socket_client *
+unix_socket_client_list_add(struct unix_socket_client_list *client_list,
+    int sock, size_t max_receive_size, size_t max_send_size, void *user_data)
+{
+	struct unix_socket_client *client;
+
+	client = (struct unix_socket_client *)malloc(sizeof(*client));
+	if (client == NULL) {
+		return (NULL);
+	}
+
+	unix_socket_client_init(client, sock, max_receive_size, max_send_size, user_data);
+
+	TAILQ_INSERT_TAIL(client_list, client, entries);
+
+	return (client);
+}
+
+void
+unix_socket_client_list_free(struct unix_socket_client_list *client_list)
+{
+	struct unix_socket_client *client;
+	struct unix_socket_client *client_next;
+
+	client = TAILQ_FIRST(client_list);
+
+	while (client != NULL) {
+		client_next = TAILQ_NEXT(client, entries);
+
+		unix_socket_client_destroy(client);
+		free(client);
+
+		client = client_next;
+	}
+
+	TAILQ_INIT(client_list);
+}
+
+void
+unix_socket_client_list_del(struct unix_socket_client_list *client_list,
+    struct unix_socket_client *client)
+{
+
+	TAILQ_REMOVE(client_list, client, entries);
+	unix_socket_client_destroy(client);
+	free(client);
+}
+
+size_t
+unix_socket_client_list_no_clients(struct unix_socket_client_list *client_list)
+{
+	size_t res;
+	struct unix_socket_client *client;
+
+	res = 0;
+
+	TAILQ_FOREACH(client, client_list, entries) {
+		res++;
+	}
+
+	return (res);
+}

+ 69 - 0
qdevices/unix-socket-client-list.h

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _UNIX_SOCKET_CLIENT_LIST_H_
+#define _UNIX_SOCKET_CLIENT_LIST_H_
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include "unix-socket-client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+TAILQ_HEAD(unix_socket_client_list, unix_socket_client);
+
+extern void				 unix_socket_client_list_init(
+    struct unix_socket_client_list *client_list);
+
+extern struct unix_socket_client	*unix_socket_client_list_add(
+    struct unix_socket_client_list *client_list,
+    int sock, size_t max_receive_size, size_t max_send_size, void *user_data);
+
+extern void				 unix_socket_client_list_free(
+    struct unix_socket_client_list *client_list);
+
+extern void				 unix_socket_client_list_del(
+    struct unix_socket_client_list *client_list, struct unix_socket_client *client);
+
+extern size_t				 unix_socket_client_list_no_clients(
+    struct unix_socket_client_list *client_list);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UNIX_SOCKET_CLIENT_LIST_H_ */

+ 14 - 30
qdevices/qdevice-local-socket.c → qdevices/unix-socket-client.c

@@ -32,42 +32,26 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "qdevice-config.h"
-#include "qdevice-log.h"
-#include "qdevice-local-socket.h"
-#include "unix-socket.h"
+#include <string.h>
 
-int
-qdevice_local_socket_init(struct qdevice_instance *instance)
-{
-	int local_socket;
-
-	local_socket = unix_socket_server_create(QDEVICE_LOCAL_SOCKET_FILE, 1,
-	    QDEVICE_LOCAL_SOCKET_BACKLOG);
-	if (local_socket < 0) {
-		qdevice_log_err(LOG_ERR, "Can't create unix socket");
-		return (-1);
-	}
+#include "unix-socket-client.h"
 
-	instance->local_socket_fd = local_socket;
+void
+unix_socket_client_init(struct unix_socket_client *client, int sock, size_t max_receive_size,
+    size_t max_send_size, void *user_data)
+{
 
-	return (0);
+	memset(client, 0, sizeof(*client));
+	client->socket = sock;
+	client->user_data = user_data;
+	dynar_init(&client->receive_buffer, max_receive_size);
+	dynar_init(&client->send_buffer, max_send_size);
 }
 
 void
-qdevice_local_socket_destroy(struct qdevice_instance *instance)
+unix_socket_client_destroy(struct unix_socket_client *client)
 {
 
-	if (instance->local_socket_fd < 0) {
-		return ;
-	}
-
-	if (close(instance->local_socket_fd) != 0) {
-		qdevice_log_err(LOG_WARNING, "Can't close unix socket");
-	}
-
-	instance->local_socket_fd = -1;
-	if (unlink(QDEVICE_LOCAL_SOCKET_FILE) != 0) {
-		qdevice_log_err(LOG_WARNING, "Can't unlink unix socket");
-	}
+	dynar_destroy(&client->send_buffer);
+	dynar_destroy(&client->receive_buffer);
 }

+ 69 - 0
qdevices/unix-socket-client.h

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _UNIX_SOCKET_CLIENT_H_
+#define _UNIX_SOCKET_CLIENT_H_
+
+#include <sys/types.h>
+
+#include <sys/queue.h>
+#include <inttypes.h>
+
+#include "dynar.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct unix_socket_client {
+	int socket;
+	struct dynar receive_buffer;
+	struct dynar send_buffer;
+	size_t msg_already_received_bytes;
+	size_t msg_already_sent_bytes;
+	int schedule_disconnect;
+	void *user_data;
+	TAILQ_ENTRY(unix_socket_client) entries;
+};
+
+extern void		unix_socket_client_init(struct unix_socket_client *client, int sock,
+    size_t max_receive_size, size_t max_send_size, void *user_data);
+
+extern void		unix_socket_client_destroy(struct unix_socket_client *client);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UNIX_SOCKET_CLIENT_H_ */

+ 127 - 0
qdevices/unix-socket-ipc.c

@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unix-socket.h"
+#include "unix-socket-ipc.h"
+
+int
+unix_socket_ipc_init(struct unix_socket_ipc *ipc, const char *socket_file_name, int backlog,
+    size_t max_clients, size_t max_receive_size, size_t max_send_size)
+{
+
+	memset(ipc, 0, sizeof(*ipc));
+
+	ipc->socket_file_name = strdup(socket_file_name);
+	if (ipc->socket_file_name == NULL) {
+		return (-1);
+	}
+
+	unix_socket_client_list_init(&ipc->clients);
+
+	ipc->backlog = backlog;
+	ipc->socket = unix_socket_server_create(ipc->socket_file_name, 1,
+		backlog);
+	if (ipc->socket < 0) {
+		free(ipc->socket_file_name);
+		return (-1);
+	}
+
+	ipc->max_clients = max_clients;
+	ipc->max_receive_size = max_receive_size;
+	ipc->max_send_size = max_send_size;
+
+	return (0);
+}
+
+int
+unix_socket_ipc_destroy(struct unix_socket_ipc *ipc)
+{
+	int res;
+
+	res = 0;
+
+	if (ipc->socket < 0) {
+		return (0);
+	}
+
+	if (unix_socket_server_destroy(ipc->socket, ipc->socket_file_name) != 0) {
+		res = -1;
+	}
+
+	free(ipc->socket_file_name);
+	ipc->socket_file_name = NULL;
+
+	ipc->socket = -1;
+
+	return (res);
+}
+
+/*
+ *  0 = No error
+ * -1 = Can't accept connection (errno set)
+ * -2 = Too much clients
+ * -3 = Can't add client to list
+ */
+int
+unix_socket_ipc_accept(struct unix_socket_ipc *ipc, struct unix_socket_client **res_client)
+{
+	int client_sock;
+	struct unix_socket_client *client;
+
+	if ((client_sock = unix_socket_server_accept(ipc->socket, 1)) < 0) {
+		return (-1);
+	}
+
+	if (ipc->max_clients != 0 &&
+	    unix_socket_client_list_no_clients(&ipc->clients) >= ipc->max_clients) {
+		unix_socket_close(client_sock);
+
+		return (-2);
+	}
+
+	client = unix_socket_client_list_add(&ipc->clients, client_sock, ipc->max_receive_size,
+	    ipc->max_send_size, NULL);
+	if (client == NULL) {
+		unix_socket_close(client_sock);
+
+		return (-3);
+	}
+
+	*res_client = client;
+
+	return (0);
+}

+ 68 - 0
qdevices/unix-socket-ipc.h

@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _UNIX_SOCKET_IPC_H_
+#define _UNIX_SOCKET_IPC_H_
+
+#include "unix-socket-client.h"
+#include "unix-socket-client-list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct unix_socket_ipc {
+	int socket;
+	int backlog;
+	char *socket_file_name;
+	struct unix_socket_client_list clients;
+	size_t max_clients;
+	size_t max_receive_size;
+	size_t max_send_size;
+};
+
+extern int		unix_socket_ipc_init(struct unix_socket_ipc *ipc,
+    const char *socket_file_name, int backlog, size_t max_clients, size_t max_receive_size,
+    size_t max_send_size);
+
+extern int		unix_socket_ipc_destroy(struct unix_socket_ipc *ipc);
+
+extern int		unix_socket_ipc_accept(struct unix_socket_ipc *ipc,
+    struct unix_socket_client **res_client);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UNIX_SOCKET_IPC_H_ */

+ 48 - 0
qdevices/unix-socket.c

@@ -102,3 +102,51 @@ unix_socket_server_create(const char *path, int non_blocking, int backlog)
 
 	return (s);
 }
+
+int
+unix_socket_server_destroy(int sock, const char *path)
+{
+	int res;
+
+	res = 0;
+
+	if (close(sock) != 0) {
+		res = -1;
+	}
+
+	if (unlink(path) != 0) {
+		res = -1;
+	}
+
+	return (res);
+}
+
+int
+unix_socket_server_accept(int sock, int non_blocking)
+{
+	struct sockaddr_un sun;
+	socklen_t sun_len;
+	int client_sock;
+
+	sun_len = sizeof(sun);
+	if ((client_sock = accept(sock, (struct sockaddr *)&sun, &sun_len)) < 0) {
+		return (-1);
+	}
+
+	if (non_blocking) {
+		if (unix_socket_set_non_blocking(client_sock) != 0) {
+			close(client_sock);
+
+			return (-1);
+		}
+	}
+
+	return (client_sock);
+}
+
+int
+unix_socket_close(int sock)
+{
+
+	return (close(sock));
+}

+ 6 - 0
qdevices/unix-socket.h

@@ -44,6 +44,12 @@ extern "C" {
 
 extern int		unix_socket_server_create(const char *path, int non_blocking, int backlog);
 
+extern int		unix_socket_server_destroy(int sock, const char *path);
+
+extern int		unix_socket_server_accept(int sock, int non_blocking);
+
+extern int		unix_socket_close(int sock);
+
 #ifdef __cplusplus
 }
 #endif