aboutsummaryrefslogtreecommitdiffstats
path: root/src/servers/master.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2019-10-22 15:04:45 +0200
committerMattias Andrée <maandree@kth.se>2019-10-22 15:04:45 +0200
commitb13efce73e506b0feb4bb7c275c273a54ae6e716 (patch)
tree79f93e69b01d236e96037aa60332d214696e048b /src/servers/master.c
parentFix NULL-pointer bug in get_pathname when running with -mdrm (diff)
downloadcoopgammad-1.3.tar.gz
coopgammad-1.3.tar.bz2
coopgammad-1.3.tar.xz
Change license and style, reorganise file, make makefile portable, and fix bugs1.3
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src/servers/master.c')
-rw-r--r--src/servers/master.c394
1 files changed, 0 insertions, 394 deletions
diff --git a/src/servers/master.c b/src/servers/master.c
deleted file mode 100644
index 01b9bb5..0000000
--- a/src/servers/master.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/**
- * coopgammad -- Cooperative gamma server
- * Copyright (C) 2016 Mattias Andrée (maandree@kth.se)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include "master.h"
-#include "crtc.h"
-#include "gamma.h"
-#include "coopgamma.h"
-#include "../util.h"
-#include "../communication.h"
-#include "../state.h"
-
-#include <sys/socket.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-
-
-/**
- * All poll(3p) events that are not for writing
- */
-#define NON_WR_POLL_EVENTS (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLERR | POLLHUP | POLLNVAL)
-
-
-/**
- * Extract headers from an inbound message and pass
- * them on to appropriate message handling function
- *
- * @param conn The index of the connection
- * @param msg The inbound message
- * @return 1: The connection as closed
- * 0: Successful
- * -1: Failure
- */
-static int dispatch_message(size_t conn, struct message* restrict msg)
-{
- size_t i;
- int r = 0;
- const char* header;
- const char* value;
- const char* command = NULL;
- const char* crtc = NULL;
- const char* coalesce = NULL;
- const char* high_priority = NULL;
- const char* low_priority = NULL;
- const char* priority = NULL;
- const char* class = NULL;
- const char* lifespan = NULL;
- const char* message_id = NULL;
-
- for (i = 0; i < msg->header_count; i++)
- {
- value = strstr((header = msg->headers[i]), ": ") + 2;
- if (strstr(header, "Command: ") == header) command = value;
- else if (strstr(header, "CRTC: ") == header) crtc = value;
- else if (strstr(header, "Coalesce: ") == header) coalesce = value;
- else if (strstr(header, "High priority: ") == header) high_priority = value;
- else if (strstr(header, "Low priority: ") == header) low_priority = value;
- else if (strstr(header, "Priority: ") == header) priority = value;
- else if (strstr(header, "Class: ") == header) class = value;
- else if (strstr(header, "Lifespan: ") == header) lifespan = value;
- else if (strstr(header, "Message ID: ") == header) message_id = value;
- else if (strstr(header, "Length: ") == header) ;/* Handled transparently */
- else
- fprintf(stderr, "%s: ignoring unrecognised header: %s\n", argv0, header);
- }
-
- if (command == NULL)
- fprintf(stderr, "%s: ignoring message without Command header\n", argv0);
- else if (message_id == NULL)
- fprintf(stderr, "%s: ignoring message without Message ID header\n", argv0);
- else if (!strcmp(command, "enumerate-crtcs"))
- {
- if (crtc || coalesce || high_priority || low_priority || priority || class || lifespan)
- fprintf(stderr, "%s: ignoring superfluous headers in Command: enumerate-crtcs message\n", argv0);
- r = handle_enumerate_crtcs(conn, message_id);
- }
- else if (!strcmp(command, "get-gamma-info"))
- {
- if (coalesce || high_priority || low_priority || priority || class || lifespan)
- fprintf(stderr, "%s: ignoring superfluous headers in Command: get-gamma-info message\n", argv0);
- r = handle_get_gamma_info(conn, message_id, crtc);
- }
- else if (!strcmp(command, "get-gamma"))
- {
- if (priority || class || lifespan)
- fprintf(stderr, "%s: ignoring superfluous headers in Command: get-gamma message\n", argv0);
- r = handle_get_gamma(conn, message_id, crtc, coalesce, high_priority, low_priority);
- }
- else if (!strcmp(command, "set-gamma"))
- {
- if (coalesce || high_priority || low_priority)
- fprintf(stderr, "%s: ignoring superfluous headers in Command: set-gamma message\n", argv0);
- r = handle_set_gamma(conn, message_id, crtc, priority, class, lifespan);
- }
- else
- fprintf(stderr, "%s: ignoring unrecognised command: Command: %s\n", argv0, command);
-
- return r;
-}
-
-
-/**
- * Sets the file descriptor set that includes
- * the server socket and all connections
- *
- * The file descriptor will be ordered as in
- * the array `connections`, `socketfd` will
- * be last.
- *
- * @param fds Reference parameter for the array of file descriptors
- * @param fdn Output parameter for the number of file descriptors
- * @param fds_alloc Reference parameter for the allocation size of `fds`, in elements
- * @return Zero on success, -1 on error
- */
-static int update_fdset(struct pollfd** restrict fds, nfds_t* restrict fdn, nfds_t* restrict fds_alloc)
-{
- size_t i;
- nfds_t j = 0;
-
- if (connections_used + 1 > *fds_alloc)
- {
- void* new = realloc(*fds, (connections_used + 1) * sizeof(**fds));
- if (new == NULL)
- return -1;
- *fds = new;
- *fds_alloc = connections_used + 1;
- }
-
- for (i = 0; i < connections_used; i++)
- if (connections[i] >= 0)
- {
- (*fds)[j].fd = connections[i];
- (*fds)[j].events = NON_WR_POLL_EVENTS;
- j++;
- }
-
- (*fds)[j].fd = socketfd;
- (*fds)[j].events = NON_WR_POLL_EVENTS;
- j++;
-
- *fdn = j;
- return 0;
-}
-
-
-/**
- * Handle event on the server socket
- *
- * @return 1: New connection accepted
- * 0: Successful
- * -1: Failure
- */
-static int handle_server(void)
-{
- int fd, flags, saved_errno;
-
- fd = accept(socketfd, NULL, NULL);
- if (fd < 0)
- switch (errno)
- {
- case EINTR:
- return 0;
- case ECONNABORTED:
- case EINVAL:
- terminate = 1;
- return 0;
- default:
- return -1;
- }
-
- flags = fcntl(fd, F_GETFL);
- if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
- goto fail;
-
- if (connections_ptr == connections_alloc)
- {
- void* new;
-
- new = realloc(connections, (connections_alloc + 10) * sizeof(*connections));
- if (new == NULL)
- goto fail;
- connections = new;
- connections[connections_ptr] = fd;
-
- new = realloc(outbound, (connections_alloc + 10) * sizeof(*outbound));
- if (new == NULL)
- goto fail;
- outbound = new;
- ring_initialise(outbound + connections_ptr);
-
- new = realloc(inbound, (connections_alloc + 10) * sizeof(*inbound));
- if (new == NULL)
- goto fail;
- inbound = new;
- connections_alloc += 10;
- if (message_initialise(inbound + connections_ptr))
- goto fail;
- }
- else
- {
- connections[connections_ptr] = fd;
- ring_initialise(outbound + connections_ptr);
- if (message_initialise(inbound + connections_ptr))
- goto fail;
- }
-
- connections_ptr++;
- while ((connections_ptr < connections_used) && (connections[connections_ptr] >= 0))
- connections_ptr++;
- if (connections_used < connections_ptr)
- connections_used = connections_ptr;
-
- return 1;
- fail:
- saved_errno = errno;
- shutdown(fd, SHUT_RDWR);
- close(fd);
- errno = saved_errno;
- return -1;
-}
-
-
-/**
- * Handle event on a connection to a client
- *
- * @param conn The index of the connection
- * @return 1: The connection as closed
- * 0: Successful
- * -1: Failure
- */
-static int handle_connection(size_t conn)
-{
- struct message* restrict msg = inbound + conn;
- int r, fd = connections[conn];
-
- again:
- switch (message_read(msg, fd))
- {
- default:
- break;
- case -1:
- switch (errno)
- {
- case EINTR:
- case EAGAIN:
-#if EAGAIN != EWOULDBLOCK
- case EWOULDBLOCK:
-#endif
- return 0;
- default:
- return -1;
- case ECONNRESET:;
- /* Fall throught to `case -2` in outer switch */
- }
- case -2:
- shutdown(fd, SHUT_RDWR);
- close(fd);
- connections[conn] = -1;
- if (conn < connections_ptr)
- connections_ptr = conn;
- while ((connections_used > 0) && (connections[connections_used - 1] < 0))
- connections_used -= 1;
- message_destroy(msg);
- ring_destroy(outbound + conn);
- if (connection_closed(fd) < 0)
- return -1;
- return 1;
- }
-
- if ((r = dispatch_message(conn, msg)))
- return r;
-
- goto again;
-}
-
-
-
-/**
- * Disconnect all clients
- */
-void disconnect_all(void)
-{
- size_t i;
- for (i = 0; i < connections_used; i++)
- if (connections[i] >= 0)
- {
- shutdown(connections[i], SHUT_RDWR);
- close(connections[i]);
- }
-}
-
-
-/**
- * The program's main loop
- *
- * @return Zero on success, -1 on error
- */
-int main_loop(void)
-{
- struct pollfd* fds = NULL;
- nfds_t i, fdn = 0, fds_alloc = 0;
- int r, update, saved_errno;
- size_t j;
-
- if (update_fdset(&fds, &fdn, &fds_alloc) < 0)
- goto fail;
-
- while (!reexec && !terminate)
- {
- if (connection)
- {
- if ((connection == 1 ? disconnect() : reconnect()) < 0)
- {
- connection = 0;
- goto fail;
- }
- connection = 0;
- }
-
- for (j = 0, i = 0; j < connections_used; j++)
- if (connections[j] >= 0)
- {
- fds[i].revents = 0;
- if (ring_have_more(outbound + j))
- fds[(size_t)i++ + j].events |= POLLOUT;
- else
- fds[(size_t)i++ + j].events &= ~POLLOUT;
- }
- fds[i].revents = 0;
-
- if (poll(fds, fdn, -1) < 0)
- {
- if (errno == EAGAIN)
- perror(argv0);
- else if (errno != EINTR)
- goto fail;
- }
-
- update = 0;
- for (i = 0; i < fdn; i++)
- {
- int do_read = fds[i].revents & NON_WR_POLL_EVENTS;
- int do_write = fds[i].revents & POLLOUT;
- int fd = fds[i].fd;
- if (!do_read && !do_write)
- continue;
-
- if (fd == socketfd)
- r = handle_server();
- else
- {
- for (j = 0; connections[j] != fd; j++);
- r = do_read ? handle_connection(j) : 0;
- }
-
- if ((r >= 0) && do_write)
- r |= continue_send(j);
- if (r < 0)
- goto fail;
- update |= (r > 0);
- }
- if (update)
- if (update_fdset(&fds, &fdn, &fds_alloc) < 0)
- goto fail;
- }
-
- free(fds);
- return 0;
- fail:
- saved_errno = errno;
- free(fds);
- errno = saved_errno;
- return -1;
-}
-