From: Jan Friesse Date: Wed, 12 Aug 2020 12:36:24 +0000 (+0200) Subject: qnetd: Migrate main loop to pr-poll-loop X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=6f55a0649f2e65d6e45421e6d2a87e8377822142;p=mirror_corosync-qdevice.git qnetd: Migrate main loop to pr-poll-loop Signed-off-by: Jan Friesse --- diff --git a/qdevices/Makefile.am b/qdevices/Makefile.am index df8cb0b..1fb496b 100644 --- a/qdevices/Makefile.am +++ b/qdevices/Makefile.am @@ -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 diff --git a/qdevices/corosync-qnetd.c b/qdevices/corosync-qnetd.c index 1386cd8..b611293 100644 --- a/qdevices/corosync-qnetd.c +++ b/qdevices/corosync-qnetd.c @@ -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); diff --git a/qdevices/qnetd-client-net.c b/qdevices/qnetd-client-net.c index 9a91ac6..f25c64e 100644 --- a/qdevices/qnetd-client-net.c +++ b/qdevices/qnetd-client-net.c @@ -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: diff --git a/qdevices/qnetd-dpd-timer.c b/qdevices/qnetd-dpd-timer.c index c23aa2e..42f7ca9 100644 --- a/qdevices/qnetd-dpd-timer.c +++ b/qdevices/qnetd-dpd-timer.c @@ -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; } } diff --git a/qdevices/qnetd-instance.c b/qdevices/qnetd-instance.c index 331838c..a0bc9ed 100644 --- a/qdevices/qnetd-instance.c +++ b/qdevices/qnetd-instance.c @@ -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); } diff --git a/qdevices/qnetd-instance.h b/qdevices/qnetd-instance.h index d2c4733..03cfbad 100644 --- a/qdevices/qnetd-instance.h +++ b/qdevices/qnetd-instance.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016 Red Hat, Inc. + * Copyright (c) 2015-2020 Red Hat, Inc. * * All rights reserved. * @@ -45,9 +45,10 @@ #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, diff --git a/qdevices/qnetd-ipc.c b/qdevices/qnetd-ipc.c index 5672624..3a981e0 100644 --- a/qdevices/qnetd-ipc.c +++ b/qdevices/qnetd-ipc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 Red Hat, Inc. + * Copyright (c) 2015-2020 Red Hat, Inc. * * All rights reserved. * @@ -45,6 +45,144 @@ */ #include +/* + * 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); } diff --git a/qdevices/qnetd-ipc.h b/qdevices/qnetd-ipc.h index b8fbdd8..599c2f3 100644 --- a/qdevices/qnetd-ipc.h +++ b/qdevices/qnetd-ipc.h @@ -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 index 336e41f..0000000 --- a/qdevices/qnetd-poll-array-user-data.h +++ /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_ */