Browse Source

lib: Add ktpd_clients database

Serj Kalichev 3 years ago
parent
commit
8eb0a3e1ca
7 changed files with 226 additions and 106 deletions
  1. 41 95
      bin/klishd/klishd.c
  2. 2 1
      klish/ktp/Makefile.am
  3. 1 1
      klish/ktp/ktp_session.c
  4. 152 0
      klish/ktp/ktpd_clients.c
  5. 7 6
      klish/ktp/ktpd_session.c
  6. 7 1
      klish/ktp/private.h
  7. 16 2
      klish/ktp_session.h

+ 41 - 95
bin/klishd/klishd.c

@@ -35,8 +35,11 @@
 
 #include "private.h"
 
+
+// Local static functions
 static int create_listen_unix_sock(const char *path);
 
+
 // Main loop events
 static bool_t stop_loop_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
 	void *associated_data, void *user_data);
@@ -61,9 +64,8 @@ int main(int argc, char **argv)
 	int pidfd = -1;
 	int logoptions = 0;
 	faux_eloop_t *eloop = NULL;
-
-	// Network
 	int listen_unix_sock = -1;
+	ktpd_clients_t *clients = NULL;
 
 	struct timespec delayed = { .tv_sec = 10, .tv_nsec = 0 };
 	struct timespec period = { .tv_sec = 3, .tv_nsec = 0 };
@@ -125,13 +127,20 @@ int main(int argc, char **argv)
 		}
 	}
 
-	// Network initialization
+	// Listen socket
 	syslog(LOG_DEBUG, "Create listen UNIX socket: %s\n", opts->unix_socket_path);
 	listen_unix_sock = create_listen_unix_sock(opts->unix_socket_path);
 	if (listen_unix_sock < 0)
 		goto err;
 	syslog(LOG_DEBUG, "Listen socket %d", listen_unix_sock);
 
+	// Clients sessions DB
+	clients = ktpd_clients_new();
+	assert(clients);
+	if (!clients)
+		goto err;
+
+	// Event loop
 	eloop = faux_eloop_new(NULL);
 	// Signals
 	faux_eloop_add_signal(eloop, SIGINT, stop_loop_ev, NULL);
@@ -139,7 +148,7 @@ int main(int argc, char **argv)
 	faux_eloop_add_signal(eloop, SIGQUIT, stop_loop_ev, NULL);
 	faux_eloop_add_signal(eloop, SIGHUP, refresh_config_ev, opts);
 	// Listen socket. Waiting for new connections
-	faux_eloop_add_fd(eloop, listen_unix_sock, POLLIN, listen_socket_ev, NULL);
+	faux_eloop_add_fd(eloop, listen_unix_sock, POLLIN, listen_socket_ev, clients);
 	// Scheduled events
 	faux_eloop_add_sched_once_delayed(eloop, &delayed, 1, sched_once, NULL);
 	faux_eloop_add_sched_periodic_delayed(eloop, 2, sched_periodic, NULL, &period, FAUX_SCHED_INFINITE);
@@ -148,99 +157,10 @@ int main(int argc, char **argv)
 	faux_eloop_free(eloop);
 
 /*
-	// Main loop
-	while (!sigterm) {
-		int sn = 0;
-		struct timespec *timeout = NULL;
-		struct timespec next_interval = {};
-		faux_pollfd_iterator_t pollfd_iter;
-		struct pollfd *pollfd = NULL;
-		pid_t pid = -1;
-
-		// Re-read config file on SIGHUP
-		if (sighup) {
-			if (access(opts->cfgfile, R_OK) == 0) {
-				syslog(LOG_INFO, "Re-reading config file \"%s\"\n", opts->cfgfile);
-				if (config_parse(opts->cfgfile, opts) < 0)
-					syslog(LOG_ERR, "Error while config file parsing.\n");
-			} else if (opts->cfgfile_userdefined) {
-				syslog(LOG_ERR, "Can't find config file \"%s\"\n", opts->cfgfile);
-			}
-			sighup = 0;
-		}
-
 		// Non-blocking wait for all children
 		while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
 			syslog(LOG_DEBUG, "Exit child process %d\n", pid);
 		}
-		sigchld = 0;
-
-		// Find out timeout interval
-		if (faux_sched_next_interval(sched, &next_interval) < 0) {
-			timeout = NULL;
-		} else {
-			timeout = &next_interval;
-			syslog(LOG_DEBUG, "Next interval: %ld\n", timeout->tv_sec);
-		}
-
-		// Wait for events
-		sn = ppoll(faux_pollfd_vector(fds), faux_pollfd_len(fds), timeout, &orig_sig_set);
-		if (sn < 0) {
-			if ((EAGAIN == errno) || (EINTR == errno))
-				continue;
-			syslog(LOG_ERR, "Error while select(): %s\n", strerror(errno));
-			break;
-		}
-
-		// Timeout (Scheduled event)
-		if (0 == sn) {
-			int id = 0; // Event idenftifier
-			void *data = NULL; // Event data
-
-syslog(LOG_DEBUG, "Timeout\n");
-			// Some scheduled events
-			while(faux_sched_pop(sched, &id, &data) == 0) {
-				syslog(LOG_DEBUG, "sched: Update event\n");
-			}
-			continue;
-		}
-
-		// Get data via socket
-		faux_pollfd_init_iterator(fds, &pollfd_iter);
-		while ((pollfd = faux_pollfd_each_active(fds, &pollfd_iter))) {
-			int fd = pollfd->fd;
-
-			// Listen socket
-			if (fd == listen_unix_sock) {
-				int new_conn = -1;
-				new_conn = accept(listen_unix_sock, NULL, NULL);
-				if (new_conn < 0)
-					continue;
-				faux_pollfd_add(fds, new_conn, POLLIN);
-				syslog(LOG_DEBUG, "New connection %d", new_conn);
-				continue;
-			}
-
-			// If it's not a listen socket then we have received
-			// a message from client.
-syslog(LOG_DEBUG, "Client %d\n", fd);
-
-			// Receive message
-			
-			
-
-			// Check for closed connection. Do it after reading from
-			// socket because buffer of disconnected socket can
-			// still contain data.
-			if (pollfd->revents & POLLHUP) {
-				ktp_disconnect(fd);
-				faux_pollfd_del_by_fd(fds, fd);
-				syslog(LOG_DEBUG, "Close connection %d", fd);
-			}
-
-		}
-
-	} // Main loop end
 */
 
 	retval = 0;
@@ -248,6 +168,8 @@ syslog(LOG_DEBUG, "Client %d\n", fd);
 err:
 	syslog(LOG_DEBUG, "Cleanup.\n");
 
+	ktpd_clients_free(clients);
+
 	// Close listen socket
 	if (listen_unix_sock >= 0)
 		close(listen_unix_sock);
@@ -368,13 +290,23 @@ static bool_t listen_socket_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
 {
 	int new_conn = -1;
 	faux_eloop_info_fd_t *info = (faux_eloop_info_fd_t *)associated_data;
+	ktpd_clients_t *clients = (ktpd_clients_t *)user_data;
+	ktpd_session_t *session = NULL;
+
+	assert(clients);
 
 	new_conn = accept(info->fd, NULL, NULL);
 	if (new_conn < 0) {
 		syslog(LOG_ERR, "Can't accept() new connection");
 		return BOOL_TRUE;
 	}
-	faux_eloop_add_fd(eloop, new_conn, POLLIN, client_ev, NULL);
+	session = ktpd_clients_add(clients, new_conn);
+	if (!session) {
+		syslog(LOG_ERR, "Duplicated client fd");
+		close(new_conn);
+		return BOOL_TRUE;
+	}
+	faux_eloop_add_fd(eloop, new_conn, POLLIN, client_ev, clients);
 	syslog(LOG_DEBUG, "New connection %d", new_conn);
 
 	type = type; // Happy compiler
@@ -388,6 +320,19 @@ static bool_t client_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
 	void *associated_data, void *user_data)
 {
 	faux_eloop_info_fd_t *info = (faux_eloop_info_fd_t *)associated_data;
+	ktpd_clients_t *clients = (ktpd_clients_t *)user_data;
+	ktpd_session_t *session = NULL;
+
+	assert(clients);
+
+	// Find out session
+	session = ktpd_clients_find(clients, info->fd);
+	if (!session) { // Some strange case
+		syslog(LOG_ERR, "Can't find client session for fd %d", info->fd);
+		faux_eloop_del_fd(eloop, info->fd);
+		close(info->fd);
+		return BOOL_TRUE;
+	}
 
 	if (info->revents & POLLIN) {
 		char buf[1000];
@@ -398,9 +343,10 @@ printf("Received %ld bytes on fd %d\n", s, info->fd);
 //faux_eloop_add_signal(eloop, SIGINT, stop_loop_ev, NULL);
 	}
 
+	// EOF
 	if (info->revents & POLLHUP) {
-		close(info->fd);
 		faux_eloop_del_fd(eloop, info->fd);
+		ktpd_clients_del(clients, info->fd);
 		syslog(LOG_DEBUG, "Close connection %d", info->fd);
 	}
 

+ 2 - 1
klish/ktp/Makefile.am

@@ -1,4 +1,5 @@
 libklish_la_SOURCES += \
 	klish/ktp/ktp.c \
 	klish/ktp/ktp_session.c \
-	klish/ktp/ktpd_session.c
+	klish/ktp/ktpd_session.c \
+	klish/ktp/ktpd_clients.c

+ 1 - 1
klish/ktp/ktp_session.c

@@ -60,7 +60,7 @@ bool_t ktp_session_connected(ktp_session_t *session)
 }
 
 
-int ktp_session_get_socket(ktp_session_t *session)
+int ktp_session_fd(const ktp_session_t *session)
 {
 	assert(session);
 	if (!session)

+ 152 - 0
klish/ktp/ktpd_clients.c

@@ -0,0 +1,152 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include <faux/faux.h>
+#include <faux/str.h>
+#include <faux/list.h>
+
+#include <klish/ktp_session.h>
+
+#include "private.h"
+
+
+static int ktpd_session_compare(const void *first, const void *second)
+{
+	const ktpd_session_t *f = (const ktpd_session_t *)first;
+	const ktpd_session_t *s = (const ktpd_session_t *)second;
+
+	return (ktpd_session_fd(f) - ktpd_session_fd(s));
+}
+
+
+static int ktpd_session_kcompare(const void *key, const void *list_item)
+{
+	const int *f = (const int *)key;
+	const ktpd_session_t *s = (const ktpd_session_t *)list_item;
+
+	return (*f - ktpd_session_fd(s));
+}
+
+
+ktpd_clients_t *ktpd_clients_new(void)
+{
+	ktpd_clients_t *db = NULL;
+
+	db = faux_zmalloc(sizeof(*db));
+	assert(db);
+	if (!db)
+		return NULL;
+
+	// Init
+	db->list = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
+		ktpd_session_compare, ktpd_session_kcompare,
+		(void (*)(void *))ktpd_session_free);
+
+	return db;
+}
+
+
+/** @brief Frees.
+ */
+void ktpd_clients_free(ktpd_clients_t *db)
+{
+	if (!db)
+		return;
+
+	faux_list_free(db->list);
+	faux_free(db);
+}
+
+
+ktpd_session_t *ktpd_clients_find(const ktpd_clients_t *db, int fd)
+{
+	assert(db);
+	if (!db)
+		return NULL;
+	assert(fd >= 0);
+	if (fd < 0)
+		return NULL;
+
+	return (ktpd_session_t *)faux_list_kfind(db->list, &fd);
+}
+
+
+ktpd_session_t *ktpd_clients_add(ktpd_clients_t *db, int fd)
+{
+	ktpd_session_t *session = NULL;
+
+	assert(db);
+	if (!db)
+		return NULL;
+	assert(fd >= 0);
+	if (fd < 0)
+		return NULL;
+
+	// Already exists
+	if (ktpd_clients_find(db, fd))
+		return NULL;
+
+	session = ktpd_session_new(fd);
+	if (!session)
+		return NULL;
+
+	if (!faux_list_add(db->list, session)) {
+		ktpd_session_free(session);
+		return NULL;
+	}
+
+	return session;
+}
+
+
+int ktpd_clients_del(ktpd_clients_t *db, int fd)
+{
+	assert(db);
+	if (!db)
+		return -1;
+	assert(fd >= 0);
+	if (fd < 0)
+		return -1;
+
+	if (!faux_list_kdel(db->list, &fd))
+		return -1;
+
+	return 0;
+}
+
+
+faux_list_node_t *ktpd_clients_init_iter(const ktpd_clients_t *db)
+{
+	assert(db);
+	if (!db || !db->list)
+		return NULL;
+
+	return faux_list_head(db->list);
+}
+
+
+ktpd_session_t *ktpd_clients_each(faux_list_node_t **iter)
+{
+	return (ktpd_session_t *)faux_list_each(iter);
+}
+
+
+void ktpd_clients_debug(ktpd_clients_t *db)
+{
+	faux_list_node_t *iter = NULL;
+	ktpd_session_t *session = NULL;
+
+	assert(db);
+	if (!db)
+		return;
+
+	iter = faux_list_head(db->list);
+	if (!iter)
+		return;
+
+	while ((session = (ktpd_session_t *)faux_list_each(&iter))) {
+		printf("clients: %d\n", ktpd_session_fd(session));
+	}
+
+}

+ 7 - 6
klish/ktp/ktpd_session.c

@@ -11,6 +11,7 @@
 #include <sys/un.h>
 
 #include <faux/str.h>
+#include <faux/async.h>
 #include <klish/ktp_session.h>
 
 #include "private.h"
@@ -30,9 +31,8 @@ ktpd_session_t *ktpd_session_new(int sock)
 
 	// Init
 	session->state = KTPD_SESSION_STATE_NOT_AUTHORIZED;
-	session->net = faux_net_new();
-	assert(session->net);
-	faux_net_set_fd(session->net, sock);
+	session->async = faux_async_new(sock);
+	assert(session->async);
 
 	return session;
 }
@@ -43,7 +43,8 @@ void ktpd_session_free(ktpd_session_t *session)
 	if (!session)
 		return;
 
-	faux_net_free(session->net);
+	close(ktpd_session_fd(session));
+	faux_async_free(session->async);
 	faux_free(session);
 }
 
@@ -60,13 +61,13 @@ bool_t ktpd_session_connected(ktpd_session_t *session)
 }
 
 
-int ktpd_session_get_socket(ktpd_session_t *session)
+int ktpd_session_fd(const ktpd_session_t *session)
 {
 	assert(session);
 	if (!session)
 		return BOOL_FALSE;
 
-	return faux_net_get_fd(session->net);
+	return faux_async_fd(session->async);
 }
 
 #if 0

+ 7 - 1
klish/ktp/private.h

@@ -2,6 +2,7 @@
 #define _klish_ktp_private_h
 
 #include <faux/net.h>
+#include <faux/async.h>
 #include <klish/ktp_session.h>
 
 
@@ -17,7 +18,7 @@ struct ktpd_session_s {
 	uid_t uid;
 	gid_t gid;
 	char *user;
-	faux_net_t *net;
+	faux_async_t *async;
 };
 
 
@@ -35,4 +36,9 @@ struct ktp_session_s {
 	faux_net_t *net;
 };
 
+
+struct ktpd_clients_s {
+	faux_list_t *list;
+};
+
 #endif // _klish_ktp_private_h

+ 16 - 2
klish/ktp_session.h

@@ -1,12 +1,16 @@
 #ifndef _klish_ktp_session_h
 #define _klish_ktp_session_h
 
+#include <faux/faux.h>
+#include <faux/list.h>
+
 #define USOCK_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path)
 
 #define KLISH_DEFAULT_UNIX_SOCKET_PATH "/tmp/klish-unix-socket"
 
 typedef struct ktpd_session_s ktpd_session_t;
 typedef struct ktp_session_s ktp_session_t;
+typedef struct ktpd_clients_s ktpd_clients_t;
 
 C_DECL_BEGIN
 
@@ -14,13 +18,23 @@ C_DECL_BEGIN
 ktp_session_t *ktp_session_new(int sock);
 void ktp_session_free(ktp_session_t *session);
 bool_t ktp_session_connected(ktp_session_t *session);
-int ktp_session_get_socket(ktp_session_t *session);
+int ktp_session_fd(const ktp_session_t *session);
 
 // Server KTP session
 ktpd_session_t *ktpd_session_new(int sock);
 void ktpd_session_free(ktpd_session_t *session);
 bool_t ktpd_session_connected(ktpd_session_t *session);
-int ktpd_session_get_socket(ktpd_session_t *session);
+int ktpd_session_fd(const ktpd_session_t *session);
+
+// Server's KTP clients database
+ktpd_clients_t *ktpd_clients_new(void);
+void ktpd_clients_free(ktpd_clients_t *db);
+ktpd_session_t *ktpd_clients_find(const ktpd_clients_t *db, int fd);
+ktpd_session_t *ktpd_clients_add(ktpd_clients_t *db, int fd);
+int ktpd_clients_del(ktpd_clients_t *db, int fd);
+faux_list_node_t *ktpd_clients_init_iter(const ktpd_clients_t *db);
+ktpd_session_t *ktpd_clients_each(faux_list_node_t **iter);
+void ktpd_clients_debug(ktpd_clients_t *db);
 
 C_DECL_END