]> git.proxmox.com Git - mirror_corosync-qdevice.git/commitdiff
qnetd: Migrate main loop to pr-poll-loop
authorJan Friesse <jfriesse@redhat.com>
Wed, 12 Aug 2020 12:36:24 +0000 (14:36 +0200)
committerJan Friesse <jfriesse@redhat.com>
Wed, 12 Aug 2020 13:52:17 +0000 (15:52 +0200)
Signed-off-by: Jan Friesse <jfriesse@redhat.com>
qdevices/Makefile.am
qdevices/corosync-qnetd.c
qdevices/qnetd-client-net.c
qdevices/qnetd-dpd-timer.c
qdevices/qnetd-instance.c
qdevices/qnetd-instance.h
qdevices/qnetd-ipc.c
qdevices/qnetd-ipc.h
qdevices/qnetd-poll-array-user-data.h [deleted file]

index df8cb0bb6f000ddea6f97a83b3363dcb0973514b..1fb496b28262a1b7bdc30d766084e41f1dd934d8 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2012-2019 Red Hat, Inc.
+# Copyright (c) 2012-2020 Red Hat, Inc.
 #
 # Authors: Jan Friesse (jfriesse@redhat.com)
 #          Fabio M. Di Nitto (fdinitto@redhat.com)
@@ -70,8 +70,9 @@ corosync_qnetd_SOURCES        = corosync-qnetd.c \
                           unix-socket-client.c unix-socket-client.h \
                           unix-socket-client-list.c unix-socket-client-list.h \
                           unix-socket.c unix-socket.h qnetd-ipc-cmd.c qnetd-ipc-cmd.h \
-                          qnetd-poll-array-user-data.h qnet-config.h dynar-getopt-lex.c \
-                          dynar-getopt-lex.h qnetd-advanced-settings.c qnetd-advanced-settings.h
+                          qnet-config.h dynar-getopt-lex.c \
+                          dynar-getopt-lex.h qnetd-advanced-settings.c qnetd-advanced-settings.h \
+                          pr-poll-loop.c pr-poll-loop.h
 
 corosync_qnetd_tool_SOURCES = corosync-qnetd-tool.c unix-socket.c unix-socket.h dynar.c dynar.h \
                               dynar-str.c dynar-str.h utils.c utils.h
index 1386cd85039b63d0202791ef224a1b33ef587838..b611293e9c1b66c059c6d4afc91256423749305e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 Red Hat, Inc.
+ * Copyright (c) 2015-2020 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -53,7 +53,6 @@
 #include "qnetd-ipc.h"
 #include "qnetd-client-net.h"
 #include "qnetd-client-msg-received.h"
-#include "qnetd-poll-array-user-data.h"
 #include "utils.h"
 #include "msg.h"
 
@@ -90,230 +89,43 @@ qnetd_warn_nss(void)
        log_nss(LOG_WARNING, "NSS warning");
 }
 
-static PRPollDesc *
-qnetd_pr_poll_array_create(struct qnetd_instance *instance)
+static int
+server_socket_poll_loop_read_cb(PRFileDesc *prfd, void *user_data1, void *user_data2)
 {
-       struct pr_poll_array *poll_array;
-       const struct qnetd_client_list *client_list;
-       struct qnetd_client *client;
-       PRPollDesc *poll_desc;
-       struct qnetd_poll_array_user_data *user_data;
-       const struct unix_socket_client_list *ipc_client_list;
-       struct unix_socket_client *ipc_client;
-
-       poll_array = &instance->poll_array;
-       client_list = &instance->clients;
-       ipc_client_list = &instance->local_ipc.clients;
-
-       pr_poll_array_clean(poll_array);
-
-       if (pr_poll_array_add(poll_array, &poll_desc, (void **)&user_data) < 0) {
-               return (NULL);
-       }
-
-       poll_desc->fd = instance->server.socket;
-       poll_desc->in_flags = PR_POLL_READ;
-
-       user_data->type = QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET;
-
-       if (qnetd_ipc_is_closed(instance)) {
-               log(LOG_DEBUG, "Listening socket is closed");
-
-               return (NULL);
-       }
-
-       if (pr_poll_array_add(poll_array, &poll_desc, (void **)&user_data) < 0) {
-               return (NULL);
-       }
-
-       poll_desc->fd = instance->ipc_socket_poll_fd;
-       poll_desc->in_flags = PR_POLL_READ;
-       user_data->type = QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET;
-
-       TAILQ_FOREACH(client, client_list, entries) {
-               if (pr_poll_array_add(poll_array, &poll_desc, (void **)&user_data) < 0) {
-                       return (NULL);
-               }
-               poll_desc->fd = client->socket;
-               poll_desc->in_flags = PR_POLL_READ;
-
-               if (!send_buffer_list_empty(&client->send_buffer_list)) {
-                       poll_desc->in_flags |= PR_POLL_WRITE;
-               }
-
-               user_data->type = QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT;
-               user_data->client = client;
-       }
-
-       TAILQ_FOREACH(ipc_client, ipc_client_list, entries) {
-               if (!ipc_client->reading_line && !ipc_client->writing_buffer) {
-                       continue;
-               }
-
-               if (pr_poll_array_add(poll_array, &poll_desc, (void **)&user_data) < 0) {
-                       return (NULL);
-               }
+       struct qnetd_instance *instance = (struct qnetd_instance *)user_data1;
 
-               poll_desc->fd = ((struct qnetd_ipc_user_data *)ipc_client->user_data)->nspr_poll_fd;
-               if (ipc_client->reading_line) {
-                       poll_desc->in_flags |= PR_POLL_READ;
-               }
+       qnetd_client_net_accept(instance);
 
-               if (ipc_client->writing_buffer) {
-                       poll_desc->in_flags |= PR_POLL_WRITE;
-               }
+       return (0);
+}
 
-               user_data->type = QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT;
-               user_data->ipc_client = ipc_client;
-       }
+static int
+server_socket_poll_loop_write_cb(PRFileDesc *prfd, void *user_data1, void *user_data2)
+{
 
-       pr_poll_array_gc(poll_array);
+       /*
+        * Poll write on listen socket -> fatal error
+        */
+       log(LOG_CRIT, "POLL_WRITE on listening socket");
 
-       return (poll_array->array);
+       return (-1);
 }
 
 static int
-qnetd_poll(struct qnetd_instance *instance)
+server_socket_poll_loop_err_cb(PRFileDesc *prfd, short revents, void *user_data1, void *user_data2)
 {
-       struct qnetd_client *client;
-       PRPollDesc *pfds;
-       PRInt32 poll_res;
-       ssize_t i;
-       int client_disconnect;
-       struct qnetd_poll_array_user_data *user_data;
-       struct unix_socket_client *ipc_client;
-
-       client = NULL;
-       client_disconnect = 0;
-
-       pfds = qnetd_pr_poll_array_create(instance);
-       if (pfds == NULL) {
-               return (-1);
-       }
-
-       if ((poll_res = PR_Poll(pfds, pr_poll_array_size(&instance->poll_array),
-           timer_list_time_to_expire(&instance->main_timer_list))) >= 0) {
-               timer_list_expire(&instance->main_timer_list);
 
+       if (revents != POLLNVAL) {
                /*
-                * Walk thru pfds array and process events
+                * Poll ERR on listening socket is fatal error.
+                * POLL_NVAL is used as a signal to quit poll loop.
                 */
-               for (i = 0; i < pr_poll_array_size(&instance->poll_array); i++) {
-                       user_data = pr_poll_array_get_user_data(&instance->poll_array, i);
-
-                       client = NULL;
-                       ipc_client = NULL;
-                       client_disconnect = 0;
-
-                       switch (user_data->type) {
-                       case QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET:
-                               break;
-                       case QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT:
-                               client = user_data->client;
-                               client_disconnect = client->schedule_disconnect;
-                               break;
-                       case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET:
-                               break;
-                       case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT:
-                               ipc_client = user_data->ipc_client;
-                               client_disconnect = ipc_client->schedule_disconnect;
-                       }
-
-                       if (!client_disconnect && poll_res > 0 &&
-                           pfds[i].out_flags & PR_POLL_READ) {
-                               switch (user_data->type) {
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET:
-                                       qnetd_client_net_accept(instance);
-                                       break;
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT:
-                                       if (qnetd_client_net_read(instance, client) == -1) {
-                                               client_disconnect = 1;
-                                       }
-                                       break;
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET:
-                                       qnetd_ipc_accept(instance, &ipc_client);
-                                       break;
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT:
-                                       qnetd_ipc_io_read(instance, ipc_client);
-                                       break;
-                               }
-                       }
-
-                       if (!client_disconnect && poll_res > 0 &&
-                           pfds[i].out_flags & PR_POLL_WRITE) {
-                               switch (user_data->type) {
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET:
-                                       /*
-                                        * Poll write on listen socket -> fatal error
-                                        */
-                                       log(LOG_CRIT, "POLL_WRITE on listening socket");
-
-                                       return (-1);
-                                       break;
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT:
-                                       if (qnetd_client_net_write(instance, client) == -1) {
-                                               client_disconnect = 1;
-                                       }
-                                       break;
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET:
-                                       log(LOG_CRIT, "POLL_WRITE on listening IPC socket");
-                                       return (-1);
-                                       break;
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT:
-                                       qnetd_ipc_io_write(instance, ipc_client);
-                                       break;
-                               }
-                       }
-
-                       if (!client_disconnect && poll_res > 0 &&
-                           (pfds[i].out_flags & (PR_POLL_ERR|PR_POLL_NVAL|PR_POLL_HUP|PR_POLL_EXCEPT)) &&
-                           !(pfds[i].out_flags & (PR_POLL_READ|PR_POLL_WRITE))) {
-                               switch (user_data->type) {
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET:
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET:
-                                       if (pfds[i].out_flags != PR_POLL_NVAL) {
-                                               /*
-                                                * Poll ERR on listening socket is fatal error.
-                                                * POLL_NVAL is used as a signal to quit poll loop.
-                                                */
-                                                log(LOG_CRIT, "POLL_ERR (%u) on listening "
-                                                   "socket", pfds[i].out_flags);
-                                       } else {
-                                               log(LOG_DEBUG, "Listening socket is closed");
-                                       }
-
-                                       return (-1);
-                                       break;
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT:
-                                       log(LOG_DEBUG, "POLL_ERR (%u) on client socket. "
-                                           "Disconnecting.", pfds[i].out_flags);
-
-                                       client_disconnect = 1;
-                                       break;
-                               case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT:
-                                       log(LOG_DEBUG, "POLL_ERR (%u) on ipc client socket."
-                                           " Disconnecting.", pfds[i].out_flags);
-
-                                       client_disconnect = 1;
-                                       break;
-                               }
-                       }
-
-                       /*
-                        * If client is scheduled for disconnect, disconnect it
-                        */
-                       if (user_data->type == QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT &&
-                           client_disconnect) {
-                               qnetd_instance_client_disconnect(instance, client, 0);
-                       } else if (user_data->type == QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT &&
-                           (client_disconnect || ipc_client->schedule_disconnect)) {
-                               qnetd_ipc_client_disconnect(instance, ipc_client);
-                       }
-               }
+               log(LOG_CRIT, "POLL_ERR (%u) on listening socket", revents);
+       } else {
+               log(LOG_DEBUG, "Listening socket is closed");
        }
 
-
-       return (0);
+       return (-1);
 }
 
 static void
@@ -530,6 +342,7 @@ main(int argc, char * const argv[])
        int lock_file;
        int another_instance_running;
        int log_target;
+       int poll_res;
 
        if (qnetd_advanced_settings_init(&advanced_settings) != 0) {
                errx(1, "Can't alloc memory for advanced settings");
@@ -557,7 +370,7 @@ main(int argc, char * const argv[])
            advanced_settings.nss_db_dir : NULL)) != 0) {
                log_err(LOG_ERR, "Can't open NSS DB directory");
 
-               exit (1);
+               return (1);
        }
 
        /*
@@ -575,7 +388,7 @@ main(int argc, char * const argv[])
                        log_err(LOG_ERR, "Can't acquire lock");
                }
 
-               exit(1);
+               return (1);
        }
 
        log(LOG_DEBUG, "Initializing nss");
@@ -591,7 +404,7 @@ main(int argc, char * const argv[])
        if (qnetd_instance_init(&instance, tls_supported, client_cert_required,
            max_clients, &advanced_settings) == -1) {
                log(LOG_ERR, "Can't initialize qnetd");
-               exit(1);
+               return (1);
        }
        instance.host_addr = host_addr;
        instance.host_port = host_port;
@@ -621,12 +434,23 @@ main(int argc, char * const argv[])
                qnetd_err_nss();
        }
 
+       if (pr_poll_loop_add_prfd(&instance.main_poll_loop, instance.server.socket, POLLIN,
+           NULL,
+           server_socket_poll_loop_read_cb,
+           server_socket_poll_loop_write_cb,
+           server_socket_poll_loop_err_cb,
+           &instance, NULL) != 0) {
+               log(LOG_ERR, "Can't add server socket to main poll loop");
+
+               return (1);
+       }
+
        global_instance = &instance;
        signal_handlers_register();
 
        log(LOG_DEBUG, "Registering algorithms");
        if (qnetd_algorithm_register_all() != 0) {
-               exit(1);
+               return (1);
        }
 
        log(LOG_DEBUG, "QNetd ready to provide service");
@@ -638,14 +462,21 @@ main(int argc, char * const argv[])
        /*
         * MAIN LOOP
         */
-       while (qnetd_poll(&instance) == 0) {
+       while ((poll_res = pr_poll_loop_exec(&instance.main_poll_loop)) == 0) {
+       }
+
+       if (poll_res == -2) {
+               log(LOG_CRIT, "pr_poll_loop_exec returned -2 - internal error");
+               return (1);
        }
 
        /*
         * Cleanup
         */
+       log(LOG_DEBUG, "Destroying qnetd ipc");
        qnetd_ipc_destroy(&instance);
 
+       log(LOG_DEBUG, "Closing server socket");
        if (PR_Close(instance.server.socket) != PR_SUCCESS) {
                qnetd_warn_nss();
        }
@@ -669,6 +500,7 @@ main(int argc, char * const argv[])
                qnetd_warn_nss();
        }
 
+       log(LOG_DEBUG, "Closing log");
        log_close();
 
        return (0);
index 9a91ac6a25bc46ecc795ea7c61258894344c6ed8..f25c64e757c4a3f0f13f06edd544e187dd61055a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 Red Hat, Inc.
+ * Copyright (c) 2015-2020 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -56,6 +56,78 @@ qnetd_client_net_write_finished(struct qnetd_instance *instance, struct qnetd_cl
        return (0);
 }
 
+static int
+qnetd_client_net_socket_poll_loop_set_events_cb(PRFileDesc *prfd, short *events,
+    void *user_data1, void *user_data2)
+{
+       struct qnetd_instance *instance = (struct qnetd_instance *)user_data1;
+       struct qnetd_client *client = (struct qnetd_client *)user_data2;
+
+       if (client->schedule_disconnect) {
+               qnetd_instance_client_disconnect(instance, client, 0);
+
+               if (pr_poll_loop_del_prfd(&instance->main_poll_loop, prfd) == -1) {
+                       log(LOG_CRIT, "pr_poll_loop_del_prfd for client socket failed");
+
+                       return (-2);
+               }
+
+               return (-1);
+       }
+
+       if (!send_buffer_list_empty(&client->send_buffer_list)) {
+               *events |= POLLOUT;
+       }
+
+       return (0);
+}
+
+
+static int
+qnetd_client_net_socket_poll_loop_read_cb(PRFileDesc *prfd, void *user_data1, void *user_data2)
+{
+       struct qnetd_instance *instance = (struct qnetd_instance *)user_data1;
+       struct qnetd_client *client = (struct qnetd_client *)user_data2;
+
+       if (!client->schedule_disconnect) {
+               if (qnetd_client_net_read(instance, client) == -1) {
+                       client->schedule_disconnect = 1;
+               }
+       }
+
+       return (0);
+}
+
+static int
+qnetd_client_net_socket_poll_loop_write_cb(PRFileDesc *prfd, void *user_data1, void *user_data2)
+{
+       struct qnetd_instance *instance = (struct qnetd_instance *)user_data1;
+       struct qnetd_client *client = (struct qnetd_client *)user_data2;
+
+       if (!client->schedule_disconnect) {
+               if (qnetd_client_net_write(instance, client) == -1) {
+                       client->schedule_disconnect = 1;
+               }
+       }
+
+       return (0);
+}
+
+static int
+qnetd_client_net_socket_poll_loop_err_cb(PRFileDesc *prfd, short revents, void *user_data1, void *user_data2)
+{
+       struct qnetd_client *client = (struct qnetd_client *)user_data2;
+
+       if (!client->schedule_disconnect) {
+               log(LOG_DEBUG, "POLL_ERR (%u) on client socket. "
+                   "Disconnecting.", revents);
+
+               client->schedule_disconnect = 1;
+       }
+
+       return (0);
+}
+
 int
 qnetd_client_net_write(struct qnetd_instance *instance, struct qnetd_client *client)
 {
@@ -231,13 +303,25 @@ qnetd_client_net_accept(struct qnetd_instance *instance)
            client_addr_str,
            instance->advanced_settings->max_client_receive_size,
            instance->advanced_settings->max_client_send_buffers,
-           instance->advanced_settings->max_client_send_size, &instance->main_timer_list);
+           instance->advanced_settings->max_client_send_size,
+           pr_poll_loop_get_timer_list(&instance->main_poll_loop));
        if (client == NULL) {
                log(LOG_ERR, "Can't add client to list");
                res_err = -2;
                goto exit_close;
        }
 
+       if (pr_poll_loop_add_prfd(&instance->main_poll_loop, client_socket, POLLIN,
+           qnetd_client_net_socket_poll_loop_set_events_cb,
+           qnetd_client_net_socket_poll_loop_read_cb,
+           qnetd_client_net_socket_poll_loop_write_cb,
+           qnetd_client_net_socket_poll_loop_err_cb,
+           instance, client) == -1) {
+               log_err(LOG_CRIT, "Can't add client to main poll loop");
+               res_err = -2;
+               goto exit_close;
+       }
+
        return (0);
 
 exit_close:
index c23aa2e0b954eb2a03a2f62fb85c371995f8a0fa..42f7ca93b31c5190ea589ba71eec732d21b7f640 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 Red Hat, Inc.
+ * Copyright (c) 2015-2020 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -75,7 +75,7 @@ qnetd_dpd_timer_init(struct qnetd_instance *instance)
                return (0);
        }
 
-       instance->dpd_timer = timer_list_add(&instance->main_timer_list,
+       instance->dpd_timer = timer_list_add(pr_poll_loop_get_timer_list(&instance->main_poll_loop),
            instance->advanced_settings->dpd_interval,
            qnetd_dpd_timer_cb, (void *)instance, NULL);
        if (instance->dpd_timer == NULL) {
@@ -92,7 +92,7 @@ qnetd_dpd_timer_destroy(struct qnetd_instance *instance)
 {
 
        if (instance->dpd_timer != NULL) {
-               timer_list_delete(&instance->main_timer_list, instance->dpd_timer);
+               timer_list_delete(pr_poll_loop_get_timer_list(&instance->main_poll_loop), instance->dpd_timer);
                instance->dpd_timer = NULL;
        }
 }
index 331838cabf10a1b671bbf42228d4fc54680228ed..a0bc9ed228a4132dfcf124d15c82224a8bf3bc49 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 Red Hat, Inc.
+ * Copyright (c) 2015-2020 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -40,7 +40,6 @@
 #include "qnetd-algorithm.h"
 #include "qnetd-log-debug.h"
 #include "qnetd-dpd-timer.h"
-#include "qnetd-poll-array-user-data.h"
 #include "qnetd-client-algo-timer.h"
 
 int
@@ -53,7 +52,6 @@ qnetd_instance_init(struct qnetd_instance *instance,
 
        instance->advanced_settings = advanced_settings;
 
-       pr_poll_array_init(&instance->poll_array, sizeof(struct qnetd_poll_array_user_data));
        qnetd_client_list_init(&instance->clients);
        qnetd_cluster_list_init(&instance->clusters);
 
@@ -62,7 +60,7 @@ qnetd_instance_init(struct qnetd_instance *instance,
 
        instance->max_clients = max_clients;
 
-       timer_list_init(&instance->main_timer_list);
+       pr_poll_loop_init(&instance->main_poll_loop);
 
        if (qnetd_dpd_timer_init(instance) != 0) {
                return (0);
@@ -88,10 +86,10 @@ qnetd_instance_destroy(struct qnetd_instance *instance)
                client = client_next;
        }
 
-       pr_poll_array_destroy(&instance->poll_array);
        qnetd_cluster_list_free(&instance->clusters);
        qnetd_client_list_free(&instance->clients);
-       timer_list_free(&instance->main_timer_list);
+
+       pr_poll_loop_destroy(&instance->main_poll_loop);
 
        return (0);
 }
index d2c4733ed274ed4a38efa64b00d5bbcd5b7bb459..03cfbad649c28e335d7db136a2c2577383821297 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 Red Hat, Inc.
+ * Copyright (c) 2015-2020 Red Hat, Inc.
  *
  * All rights reserved.
  *
 #include "qnetd-cluster-list.h"
 #include "pr-poll-array.h"
 #include "qnet-config.h"
-#include "timer-list.h"
 #include "unix-socket-ipc.h"
 #include "qnetd-advanced-settings.h"
+#include "pr-poll-loop.h"
+#include "timer-list.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -62,16 +63,14 @@ struct qnetd_instance {
        size_t max_clients;
        struct qnetd_client_list clients;
        struct qnetd_cluster_list clusters;
-       struct pr_poll_array poll_array;
        enum tlv_tls_supported tls_supported;
        int tls_client_cert_required;
        const char *host_addr;
        uint16_t host_port;
-       struct timer_list main_timer_list;
        struct timer_list_entry *dpd_timer;             /* Dead peer detection timer */
        struct unix_socket_ipc local_ipc;
-       PRFileDesc *ipc_socket_poll_fd;
        const struct qnetd_advanced_settings *advanced_settings;
+       struct pr_poll_loop main_poll_loop;
 };
 
 extern int             qnetd_instance_init(struct qnetd_instance *instance,
index 5672624ab1e6c9619293ea35f3b19c2e6b3cebb4..3a981e0e774d0bbbe1c6445df75de02fde1bca38 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 Red Hat, Inc.
+ * Copyright (c) 2015-2020 Red Hat, Inc.
  *
  * All rights reserved.
  *
  */
 #include <private/pprio.h>
 
+/*
+ * Callbacks
+ */
+
+/*
+ * IPC server socket
+ */
+static int
+ipc_socket_poll_loop_set_events_cb(int fd, short *events, void *user_data1, void *user_data2)
+{
+       struct qnetd_instance *instance = (struct qnetd_instance *)user_data1;
+
+       if (qnetd_ipc_is_closed(instance)) {
+               log(LOG_DEBUG, "Listening socket is closed");
+
+               return (-2);
+       }
+
+       return (0);
+}
+
+static int
+ipc_socket_poll_loop_read_cb(int fd, void *user_data1, void *user_data2)
+{
+       struct qnetd_instance *instance = (struct qnetd_instance *)user_data1;
+       struct unix_socket_client *ipc_client;
+
+       qnetd_ipc_accept(instance, &ipc_client);
+
+       return (0);
+}
+
+static int
+ipc_socket_poll_loop_write_cb(int fd, void *user_data1, void *user_data2)
+{
+
+       log(LOG_CRIT, "POLL_WRITE on listening IPC socket");
+
+       return (-1);
+}
+
+static int
+ipc_socket_poll_loop_err_cb(int fd, short revents, void *user_data1, void *user_data2)
+{
+
+       if (revents != POLLNVAL) {
+               /*
+                * Poll ERR on listening socket is fatal error.
+                * POLL_NVAL is used as a signal to quit poll loop.
+                */
+               log(LOG_CRIT, "POLL_ERR (%u) on listening socket", revents);
+       } else {
+               log(LOG_DEBUG, "Listening socket is closed");
+       }
+
+       return (-1);
+}
+
+/*
+ * IPC client sockets
+ */
+static int
+ipc_client_socket_poll_loop_set_events_cb(int fd, short *events, void *user_data1, void *user_data2)
+{
+       struct qnetd_instance *instance = (struct qnetd_instance *)user_data1;
+       struct unix_socket_client *ipc_client = (struct unix_socket_client *)user_data2;
+
+       if (ipc_client->schedule_disconnect) {
+               qnetd_ipc_client_disconnect(instance, ipc_client);
+
+               if (pr_poll_loop_del_fd(&instance->main_poll_loop, fd) == -1) {
+                       log(LOG_CRIT, "pr_poll_loop_del_fd for ipc client socket failed");
+
+                       return (-2);
+               }
+
+               return (-1);
+       }
+
+       if (!ipc_client->reading_line && !ipc_client->writing_buffer) {
+               return (-1);
+       }
+
+       if (ipc_client->reading_line) {
+               *events |= POLLIN;
+       }
+
+       if (ipc_client->writing_buffer) {
+               *events |= POLLOUT;
+       }
+
+       return (0);
+}
+
+static int
+ipc_client_socket_poll_loop_read_cb(int fd, void *user_data1, void *user_data2)
+{
+       struct qnetd_instance *instance = (struct qnetd_instance *)user_data1;
+       struct unix_socket_client *ipc_client = (struct unix_socket_client *)user_data2;
+
+       if (!ipc_client->schedule_disconnect) {
+               qnetd_ipc_io_read(instance, ipc_client);
+       }
+
+       return (0);
+}
+
+static int
+ipc_client_socket_poll_loop_write_cb(int fd, void *user_data1, void *user_data2)
+{
+       struct qnetd_instance *instance = (struct qnetd_instance *)user_data1;
+       struct unix_socket_client *ipc_client = (struct unix_socket_client *)user_data2;
+
+       if (!ipc_client->schedule_disconnect) {
+               qnetd_ipc_io_write(instance, ipc_client);
+       }
+
+       return (0);
+}
+
+static int
+ipc_client_socket_poll_loop_err_cb(int fd, short revents, void *user_data1, void *user_data2)
+{
+       struct unix_socket_client *ipc_client = (struct unix_socket_client *)user_data2;
+
+       if (!ipc_client->schedule_disconnect) {
+               log(LOG_DEBUG, "POLL_ERR (%u) on ipc client socket."
+                   " Disconnecting.", revents);
+
+               ipc_client->schedule_disconnect = 1;
+       }
+
+       return (0);
+}
+
+/*
+ * Exported functions
+ */
 int
 qnetd_ipc_init(struct qnetd_instance *instance)
 {
@@ -60,8 +198,12 @@ qnetd_ipc_init(struct qnetd_instance *instance)
                return (-1);
        }
 
-       if ((instance->ipc_socket_poll_fd = PR_CreateSocketPollFd(instance->local_ipc.socket)) == NULL) {
-               log_nss(LOG_CRIT, "Can't create NSPR IPC socket poll fd");
+       if (pr_poll_loop_add_fd(&instance->main_poll_loop, instance->local_ipc.socket, POLLIN,
+           ipc_socket_poll_loop_set_events_cb,
+           ipc_socket_poll_loop_read_cb,
+           ipc_socket_poll_loop_write_cb,
+           ipc_socket_poll_loop_err_cb, instance, NULL) == -1) {
+               log_err(LOG_CRIT, "Can't add IPC socket to main poll loop");
 
                return (-1);
        }
@@ -102,10 +244,6 @@ qnetd_ipc_destroy(struct qnetd_instance *instance)
                free(client->user_data);
        }
 
-       if (PR_DestroySocketPollFd(instance->ipc_socket_poll_fd) != PR_SUCCESS) {
-               log_nss(LOG_WARNING, "Unable to destroy IPC poll socket fd");
-       }
-
        res = unix_socket_ipc_destroy(&instance->local_ipc);
        if (res != 0) {
                log_err(LOG_WARNING, "Can't destroy local IPC");
@@ -119,7 +257,6 @@ qnetd_ipc_accept(struct qnetd_instance *instance, struct unix_socket_client **re
 {
        int res;
        int accept_res;
-       PRFileDesc *prfd;
 
        accept_res = unix_socket_ipc_accept(&instance->local_ipc, res_client);
 
@@ -155,17 +292,19 @@ qnetd_ipc_accept(struct qnetd_instance *instance, struct unix_socket_client **re
        }
        memset((*res_client)->user_data, 0, sizeof(struct qnetd_ipc_user_data));
 
-       prfd = PR_CreateSocketPollFd((*res_client)->socket);
-       if (prfd == NULL) {
-               log_nss(LOG_CRIT, "Can't create NSPR poll fd for IPC client. Disconnecting client");
-               qnetd_ipc_client_disconnect(instance, *res_client);
+       if (pr_poll_loop_add_fd(&instance->main_poll_loop, (*res_client)->socket, 0,
+           ipc_client_socket_poll_loop_set_events_cb,
+           ipc_client_socket_poll_loop_read_cb,
+           ipc_client_socket_poll_loop_write_cb,
+           ipc_client_socket_poll_loop_err_cb, instance, *res_client) == -1) {
+               log_err(LOG_CRIT, "Can't add IPC client socket to main poll loop");
                res = -1;
 
+               qnetd_ipc_client_disconnect(instance, *res_client);
+
                goto return_res;
        }
 
-       ((struct qnetd_ipc_user_data *)(*res_client)->user_data)->nspr_poll_fd = prfd;
-
 return_res:
        return (res);
 }
@@ -174,12 +313,6 @@ void
 qnetd_ipc_client_disconnect(struct qnetd_instance *instance, struct unix_socket_client *client)
 {
 
-       if ((struct qnetd_ipc_user_data *)(client)->user_data != NULL &&
-           PR_DestroySocketPollFd(
-           ((struct qnetd_ipc_user_data *)(client)->user_data)->nspr_poll_fd) != PR_SUCCESS) {
-               log_nss(LOG_WARNING, "Unable to destroy client IPC poll socket fd");
-       }
-
        free(client->user_data);
        unix_socket_ipc_client_disconnect(&instance->local_ipc, client);
 }
index b8fbdd83af39ba7e029da0edc17108fd4a3df01d..599c2f365c6a50710b2797b5166206c1bf7dfe33 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 Red Hat, Inc.
+ * Copyright (c) 2015-2020 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -43,7 +43,6 @@ extern "C" {
 
 struct qnetd_ipc_user_data {
        int shutdown_requested;
-       PRFileDesc *nspr_poll_fd;
 };
 
 extern int             qnetd_ipc_init(struct qnetd_instance *instance);
diff --git a/qdevices/qnetd-poll-array-user-data.h b/qdevices/qnetd-poll-array-user-data.h
deleted file mode 100644 (file)
index 336e41f..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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 _QNETD_POLL_ARRAY_USER_DATA_H_
-#define _QNETD_POLL_ARRAY_USER_DATA_H_
-
-#include "qnetd-client.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum qnetd_poll_array_user_data_type {
-       QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET,
-       QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT,
-       QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET,
-       QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT,
-};
-
-struct qnetd_poll_array_user_data {
-       enum qnetd_poll_array_user_data_type type;
-       struct qnetd_client *client;
-       struct unix_socket_client *ipc_client;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _QNETD_POLL_ARRAY_USER_DATA_H_ */