diff options
-rw-r--r-- | kms/client/kms_client.c | 94 | ||||
-rw-r--r-- | kms/client/kms_client.h | 1 | ||||
-rw-r--r-- | kms/kms_shared.h | 2 | ||||
-rw-r--r-- | kms/server/kms_server.c | 94 |
4 files changed, 109 insertions, 82 deletions
diff --git a/kms/client/kms_client.c b/kms/client/kms_client.c index 0b28b48..05cf8d7 100644 --- a/kms/client/kms_client.c +++ b/kms/client/kms_client.c @@ -174,12 +174,10 @@ int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) { int result = -1; self->kms_server_pid = -1; self->initial_socket_fd = -1; - self->initial_client_fd = -1; self->initial_socket_path[0] = '\0'; self->socket_pair[0] = -1; self->socket_pair[1] = -1; struct sockaddr_un local_addr = {0}; - struct sockaddr_un remote_addr = {0}; if(!create_socket_path(self->initial_socket_path, sizeof(self->initial_socket_path))) { fprintf(stderr, "gsr error: gsr_kms_client_init: failed to create path to kms socket\n"); @@ -231,20 +229,6 @@ int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) { local_addr.sun_family = AF_UNIX; strncpy_safe(local_addr.sun_path, self->initial_socket_path, sizeof(local_addr.sun_path)); - const mode_t prev_mask = umask(0000); - int bind_res = bind(self->initial_socket_fd, (struct sockaddr*)&local_addr, sizeof(local_addr.sun_family) + strlen(local_addr.sun_path)); - umask(prev_mask); - - if(bind_res == -1) { - fprintf(stderr, "gsr error: gsr_kms_client_init: failed to bind socket, error: %s\n", strerror(errno)); - goto err; - } - - if(listen(self->initial_socket_fd, 1) == -1) { - fprintf(stderr, "gsr error: gsr_kms_client_init: failed to listen on socket, error: %s\n", strerror(errno)); - goto err; - } - pid_t pid = fork(); if(pid == -1) { fprintf(stderr, "gsr error: gsr_kms_client_init: fork failed, error: %s\n", strerror(errno)); @@ -271,41 +255,50 @@ int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) { self->kms_server_pid = pid; } - fprintf(stderr, "gsr info: gsr_kms_client_init: waiting for server to connect\n"); - for(;;) { - struct timeval tv; - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(self->initial_socket_fd, &rfds); - - tv.tv_sec = 0; - tv.tv_usec = 100 * 1000; // 100 ms - - int select_res = select(1 + self->initial_socket_fd, &rfds, NULL, NULL, &tv); - if(select_res > 0) { - socklen_t sock_len = 0; - self->initial_client_fd = accept(self->initial_socket_fd, (struct sockaddr*)&remote_addr, &sock_len); - if(self->initial_client_fd == -1) { - fprintf(stderr, "gsr error: gsr_kms_client_init: accept failed on socket, error: %s\n", strerror(errno)); - goto err; + fprintf(stderr, "gsr info: connecting to the server\n"); + bool connected = false; + while(true) { + struct sockaddr_un remote_addr = {0}; + remote_addr.sun_family = AF_UNIX; + strncpy_safe(remote_addr.sun_path, self->initial_socket_path, sizeof(remote_addr.sun_path)); + // TODO: Check if parent disconnected + if(connect(self->initial_socket_fd, (struct sockaddr*)&remote_addr, sizeof(remote_addr.sun_family) + strlen(remote_addr.sun_path)) == -1) { + if(errno == ECONNREFUSED || errno == ENOENT) { + goto next; + } else if(errno == EISCONN) { + connected = true; + break; } + + fprintf(stderr, "gsr error: gsr_kms_client_init: connect failed, error: %s (%d)\n", strerror(errno), errno); + goto err; + } + + next: + if(connected) break; - } else { - int status = 0; - int wait_result = waitpid(self->kms_server_pid, &status, WNOHANG); - if(wait_result != 0) { - int exit_code = -1; - if(WIFEXITED(status)) - exit_code = WEXITSTATUS(status); - fprintf(stderr, "gsr error: gsr_kms_client_init: kms server died or never started, exit code: %d\n", exit_code); - self->kms_server_pid = -1; - if(exit_code != 0) - result = exit_code; - goto err; - } + + int status = 0; + int wait_result = waitpid(self->kms_server_pid, &status, WNOHANG); + if(wait_result != 0) { + int exit_code = -1; + if(WIFEXITED(status)) + exit_code = WEXITSTATUS(status); + fprintf(stderr, "gsr error: gsr_kms_client_init: kms server died or never started, exit code: %d\n", exit_code); + self->kms_server_pid = -1; + if(exit_code != 0) + result = exit_code; + goto err; } + usleep(30 * 1000); // 30 milliseconds + } + + if(connected) { + fprintf(stderr, "gsr info: connected to the server\n"); + } else { + fprintf(stderr, "gsr error: gsr_kms_client_init: failed to connect to the server\n"); + goto err; } - fprintf(stderr, "gsr info: gsr_kms_client_init: server connected\n"); fprintf(stderr, "gsr info: replacing file-backed unix domain socket with socketpair\n"); if(gsr_kms_client_replace_connection(self) != 0) @@ -322,11 +315,6 @@ int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) { } void cleanup_socket(gsr_kms_client *self, bool kill_server) { - if(self->initial_client_fd != -1) { - close(self->initial_client_fd); - self->initial_client_fd = -1; - } - if(self->initial_socket_fd != -1) { close(self->initial_socket_fd); self->initial_socket_fd = -1; @@ -366,7 +354,7 @@ int gsr_kms_client_replace_connection(gsr_kms_client *self) { request.version = GSR_KMS_PROTOCOL_VERSION; request.type = KMS_REQUEST_TYPE_REPLACE_CONNECTION; request.new_connection_fd = self->socket_pair[GSR_SOCKET_PAIR_REMOTE]; - if(send_msg_to_server(self->initial_client_fd, &request) == -1) { + if(send_msg_to_server(self->initial_socket_fd, &request) == -1) { fprintf(stderr, "gsr error: gsr_kms_client_replace_connection: failed to send request message to server\n"); return -1; } diff --git a/kms/client/kms_client.h b/kms/client/kms_client.h index 02f2dd1..27caca2 100644 --- a/kms/client/kms_client.h +++ b/kms/client/kms_client.h @@ -8,7 +8,6 @@ typedef struct { pid_t kms_server_pid; int initial_socket_fd; - int initial_client_fd; char initial_socket_path[PATH_MAX]; int socket_pair[2]; } gsr_kms_client; diff --git a/kms/kms_shared.h b/kms/kms_shared.h index b72d75d..d31302b 100644 --- a/kms/kms_shared.h +++ b/kms/kms_shared.h @@ -4,7 +4,7 @@ #include <stdint.h> #include <stdbool.h> -#define GSR_KMS_PROTOCOL_VERSION 1 +#define GSR_KMS_PROTOCOL_VERSION 2 #define GSR_KMS_MAX_PLANES 32 typedef enum { diff --git a/kms/server/kms_server.c b/kms/server/kms_server.c index 6062074..9a64543 100644 --- a/kms/server/kms_server.c +++ b/kms/server/kms_server.c @@ -9,6 +9,7 @@ #include <fcntl.h> #include <sys/socket.h> #include <sys/un.h> +#include <sys/stat.h> #include <time.h> #include <xf86drm.h> @@ -361,6 +362,7 @@ static void strncpy_safe(char *dst, const char *src, int len) { int main(int argc, char **argv) { int res = 0; int socket_fd = 0; + int client_socket_fd = 0; gsr_drm drm; drm.drmfd = 0; drm.planes = NULL; @@ -407,36 +409,59 @@ int main(int argc, char **argv) { c2crtc_map.num_maps = 0; map_crtc_to_connector_ids(&drm, &c2crtc_map); - fprintf(stderr, "kms server info: connecting to the client\n"); + struct sockaddr_un local_addr = {0}; + local_addr.sun_family = AF_UNIX; + strncpy_safe(local_addr.sun_path, domain_socket_path, sizeof(local_addr.sun_path)); + + const mode_t prev_mask = umask(0000); + const int bind_res = bind(socket_fd, (struct sockaddr*)&local_addr, sizeof(local_addr.sun_family) + strlen(local_addr.sun_path)); + umask(prev_mask); + + if(bind_res == -1) { + fprintf(stderr, "kms server error: failed to bind socket, error: %s\n", strerror(errno)); + res = 2; + goto done; + } + + if(listen(socket_fd, 1) == -1) { + fprintf(stderr, "kms server error: failed to listen on socket, error: %s\n", strerror(errno)); + res = 2; + goto done; + } + + fprintf(stderr, "kms server info: waiting for client to connect\n"); bool connected = false; const double connect_timeout_sec = 5.0; const double start_time = clock_get_monotonic_seconds(); while(clock_get_monotonic_seconds() - start_time < connect_timeout_sec) { - struct sockaddr_un remote_addr = {0}; - remote_addr.sun_family = AF_UNIX; - strncpy_safe(remote_addr.sun_path, domain_socket_path, sizeof(remote_addr.sun_path)); - // TODO: Check if parent disconnected - if(connect(socket_fd, (struct sockaddr*)&remote_addr, sizeof(remote_addr.sun_family) + strlen(remote_addr.sun_path)) == -1) { - if(errno == ECONNREFUSED || errno == ENOENT) { - goto next; - } else if(errno == EISCONN) { - connected = true; - break; + struct timeval tv; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(socket_fd, &rfds); + + tv.tv_sec = 0; + tv.tv_usec = 100 * 1000; // 100 ms + + int select_res = select(1 + socket_fd, &rfds, NULL, NULL, &tv); + if(select_res > 0) { + struct sockaddr_un remote_addr = {0}; + socklen_t sock_len = 0; + client_socket_fd = accept(socket_fd, (struct sockaddr*)&remote_addr, &sock_len); + if(client_socket_fd == -1) { + fprintf(stderr, "kms server error: accept failed on socket, error: %s\n", strerror(errno)); + res = 2; + goto done; } - fprintf(stderr, "kms server error: connect failed, error: %s (%d)\n", strerror(errno), errno); - res = 2; - goto done; + connected = true; + break; } - - next: - usleep(30 * 1000); // 30 milliseconds } if(connected) { - fprintf(stderr, "kms server info: connected to the client\n"); + fprintf(stderr, "kms server info: client connected\n"); } else { - fprintf(stderr, "kms server error: failed to connect to the client in %f seconds\n", connect_timeout_sec); + fprintf(stderr, "kms server error: client failed to connect in %f seconds\n", connect_timeout_sec); res = 2; goto done; } @@ -447,7 +472,7 @@ int main(int argc, char **argv) { request.type = -1; request.new_connection_fd = 0; - const int recv_res = recv_msg_from_client(socket_fd, &request); + const int recv_res = recv_msg_from_client(client_socket_fd, &request); if(recv_res == 0) { fprintf(stderr, "kms server info: kms client shutdown, shutting down the server\n"); res = 3; @@ -479,18 +504,29 @@ int main(int argc, char **argv) { response.num_fds = 0; if(request.new_connection_fd > 0) { - if(socket_fd > 0) + if(socket_fd > 0) { close(socket_fd); - socket_fd = request.new_connection_fd; + socket_fd = -1; + } + + if(client_socket_fd > 0) + close(client_socket_fd); + + client_socket_fd = request.new_connection_fd; response.result = KMS_RESULT_OK; - if(send_msg_to_client(socket_fd, &response) == -1) + if(send_msg_to_client(client_socket_fd, &response) == -1) fprintf(stderr, "kms server error: failed to respond to client KMS_REQUEST_TYPE_REPLACE_CONNECTION request\n"); + + if(domain_socket_path) { + remove(domain_socket_path); + domain_socket_path = NULL; + } } else { response.result = KMS_RESULT_INVALID_REQUEST; snprintf(response.err_msg, sizeof(response.err_msg), "received invalid connection fd"); fprintf(stderr, "kms server error: %s\n", response.err_msg); - if(send_msg_to_client(socket_fd, &response) == -1) + if(send_msg_to_client(client_socket_fd, &response) == -1) fprintf(stderr, "kms server error: failed to respond to client request\n"); } @@ -502,10 +538,10 @@ int main(int argc, char **argv) { response.num_fds = 0; if(kms_get_fb(&drm, &response, &c2crtc_map) == 0) { - if(send_msg_to_client(socket_fd, &response) == -1) + if(send_msg_to_client(client_socket_fd, &response) == -1) fprintf(stderr, "kms server error: failed to respond to client KMS_REQUEST_TYPE_GET_KMS request\n"); } else { - if(send_msg_to_client(socket_fd, &response) == -1) + if(send_msg_to_client(client_socket_fd, &response) == -1) fprintf(stderr, "kms server error: failed to respond to client KMS_REQUEST_TYPE_GET_KMS request\n"); } @@ -523,7 +559,7 @@ int main(int argc, char **argv) { snprintf(response.err_msg, sizeof(response.err_msg), "invalid request type %d, expected %d (%s)", request.type, KMS_REQUEST_TYPE_GET_KMS, "KMS_REQUEST_TYPE_GET_KMS"); fprintf(stderr, "kms server error: %s\n", response.err_msg); - if(send_msg_to_client(socket_fd, &response) == -1) + if(send_msg_to_client(client_socket_fd, &response) == -1) fprintf(stderr, "kms server error: failed to respond to client request\n"); break; @@ -536,7 +572,11 @@ int main(int argc, char **argv) { drmModeFreePlaneResources(drm.planes); if(drm.drmfd > 0) close(drm.drmfd); + if(client_socket_fd > 0) + close(client_socket_fd); if(socket_fd > 0) close(socket_fd); + if(domain_socket_path) + remove(domain_socket_path); return res; } |