summaryrefslogtreecommitdiff
path: root/src/core/ev_loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/ev_loop.c')
-rw-r--r--src/core/ev_loop.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/core/ev_loop.c b/src/core/ev_loop.c
new file mode 100644
index 0000000..e084e81
--- /dev/null
+++ b/src/core/ev_loop.c
@@ -0,0 +1,206 @@
+/* BSD-2-Clause license
+ *
+ * Copyright (c) 2018-2023 NST <www.newinfosec.ru>, sss <sss at dark-alexandr dot net>.
+ *
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <ev.h>
+
+#include <webrdp_module_api.h>
+
+#include "globals.h"
+#include "remote_control.h"
+#include "thread_impl.h"
+#include "wrdp_thpool.h"
+#include "wrdp_thpool_internals.h"
+#include "ws_session.h"
+#include "socket_helpers.h"
+#include "task.h"
+#include "remote_control.h"
+
+#include "log.h"
+
+static ws_session *
+ws_create_session(int connection_fd)
+{
+ ws_session *session = 0;
+ task_info *info = 0;
+ session = calloc(1, sizeof(ws_session));
+ if (!session)
+ {
+ perror("calloc");
+ goto error;
+ }
+ info = calloc(1, sizeof(task_info));
+ if (!info)
+ {
+ perror("calloc");
+ goto error;
+ }
+ session->task_info = info;
+ session->session_state = ws_session_initial;
+ session->connection_fd = connection_fd;
+ SLIST_INIT(&(session->backend_settings_head));
+ return session;
+error:
+ if (session)
+ {
+ if (session->task_info)
+ {
+ free(session->task_info);
+ }
+ free(session);
+ }
+ return 0;
+}
+
+static void
+ws_server_cb(EV_P_ ev_io *w, int revents)
+{
+ int *sock = w->data;
+ int con = accept_new_connection(*sock);
+ if (con != -1)
+ {
+ ws_session *session = 0;
+ {
+ const char *msg = "accepting new ws connection";
+ log_msg((const uint8_t *)msg, strlen(msg),
+ wrdp_log_level_trace, 0);
+ }
+ session = ws_create_session(con);
+ if (!session)
+ {
+ close(con);
+ return;
+ }
+ if (!wrdp_thread_pool_add_task(g_globals.thpool, ws_run_session,
+ ws_session_init_cb, session))
+ {
+ const char *msg
+ = "Failed to move task to pool: pool is full";
+ log_msg((const uint8_t *)msg, strlen(msg),
+ wrdp_log_level_error, 0);
+ return;
+ }
+ }
+}
+
+static void
+ctl_server_cb(EV_P_ ev_io *w, int revents)
+{
+ int *sock = w->data;
+ int con = accept_new_connection(*sock);
+ if (con != -1)
+ {
+ const char *msg = "accepting new ctl connection";
+ log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_trace, 0);
+ ctl_task_info *info = ctl_create_task(con);
+ if (!info)
+ {
+ close(con);
+ return;
+ }
+ if (!wrdp_thread_pool_add_task(
+ g_globals.thpool, ctl_run_task, 0, info))
+ {
+ const char *msg
+ = "Failed to move task to pool: pool is full";
+ log_msg((const uint8_t *)msg, strlen(msg),
+ wrdp_log_level_error, 0);
+ return;
+ }
+ /* TODO: */
+ }
+}
+
+void
+run_ev_loop_main(int ws_tcp_sock, int ws_unix_sock, int ctl_server_sock_tcp,
+ int ctl_server_sock_unix)
+{
+ if (ws_tcp_sock == -1 && ws_unix_sock == -1)
+ {
+ const char *msg
+ = "ws: both tcp port and unix socket does not set";
+ log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0);
+ exit(EXIT_FAILURE);
+ }
+ if (ctl_server_sock_tcp == -1 && ctl_server_sock_unix == -1)
+ {
+ const char *msg
+ = "ctl: both tcp port and unix socket does not set";
+ log_msg(
+ (const uint8_t *)msg, strlen(msg), wrdp_log_level_error, 0);
+ exit(EXIT_FAILURE);
+ }
+ struct ev_loop *ev_loop = EV_DEFAULT;
+ ev_io *ws_ev_sock_acceptor, *ws_ev_unix_acceptor, *ctl_ev_sock_acceptor,
+ *ctl_ev_unix_acceptor;
+ if (ws_tcp_sock != -1)
+ {
+ int *sock = calloc(1, sizeof(int));
+ if (!sock)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+ ws_ev_sock_acceptor = calloc(1, sizeof(ev_io));
+ *sock = ws_tcp_sock;
+ ev_io_init(
+ ws_ev_sock_acceptor, ws_server_cb, ws_tcp_sock, EV_READ);
+ ws_ev_sock_acceptor->data = sock;
+ ev_io_start(ev_loop, ws_ev_sock_acceptor);
+ }
+ if (ws_unix_sock != -1)
+ {
+ int *sock = calloc(1, sizeof(int));
+ if (!sock)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+ ws_ev_unix_acceptor = calloc(1, sizeof(ev_io));
+ *sock = ws_unix_sock;
+ ev_io_init(
+ ws_ev_unix_acceptor, ws_server_cb, ws_unix_sock, EV_READ);
+ ws_ev_unix_acceptor->data = sock;
+ ev_io_start(ev_loop, ws_ev_unix_acceptor);
+ }
+ if (ctl_server_sock_tcp != -1)
+ {
+ int *sock = calloc(1, sizeof(int));
+ if (!sock)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+ ctl_ev_sock_acceptor = calloc(1, sizeof(ev_io));
+ *sock = ctl_server_sock_tcp;
+ ev_io_init(ctl_ev_sock_acceptor, ctl_server_cb,
+ ctl_server_sock_tcp, EV_READ);
+ ctl_ev_sock_acceptor->data = sock;
+ ev_io_start(ev_loop, ctl_ev_sock_acceptor);
+ }
+ if (ctl_server_sock_unix != -1)
+ {
+ int *sock = calloc(1, sizeof(int));
+ if (!sock)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+ ctl_ev_unix_acceptor = calloc(1, sizeof(ev_io));
+ *sock = ctl_server_sock_unix;
+ ev_io_init(ctl_ev_unix_acceptor, ctl_server_cb,
+ ctl_server_sock_unix, EV_READ);
+ ctl_ev_unix_acceptor->data = sock;
+ ev_io_start(ev_loop, ctl_ev_unix_acceptor);
+ }
+ ev_run(ev_loop, 0);
+}