aboutsummaryrefslogtreecommitdiffstats
path: root/pseudo_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'pseudo_server.c')
-rw-r--r--pseudo_server.c187
1 files changed, 102 insertions, 85 deletions
diff --git a/pseudo_server.c b/pseudo_server.c
index 4a474d0..931f77c 100644
--- a/pseudo_server.c
+++ b/pseudo_server.c
@@ -42,9 +42,15 @@
static int listen_fd = -1;
-int *client_fds;
-pid_t *client_pids;
-char **client_tags;
+typedef struct {
+ int fd;
+ pid_t pid;
+ char *tag;
+ char *program;
+} pseudo_client_t;
+
+pseudo_client_t *clients;
+
/* active_clients: Number of clients we actually have right now.
* highest_client: Highest index into clients table of an active client.
* max_clients: Size of table.
@@ -178,18 +184,17 @@ pseudo_server_start(int daemonize) {
/* mess with internal tables as needed */
static void
open_client(int fd) {
- int *new_client_fds;
- pid_t *new_client_pids;
- char **new_client_tags;
+ pseudo_client_t *new_clients;
int i;
/* if possible, use first open client slot */
for (i = 0; i < max_clients; ++i) {
- if (client_fds[i] == -1) {
+ if (clients[i].fd == -1) {
pseudo_debug(2, "reusing client %d for fd %d\n", i, fd);
- client_fds[i] = fd;
- client_pids[i] = 0;
- client_tags[i] = 0;
+ clients[i].fd = fd;
+ clients[i].pid = 0;
+ clients[i].tag = NULL;
+ clients[i].program = NULL;
++active_clients;
if (i > highest_client)
highest_client = i;
@@ -198,37 +203,26 @@ open_client(int fd) {
}
/* otherwise, allocate a new one */
- new_client_fds = malloc(sizeof(int) * (max_clients + 16));
- new_client_pids = malloc(sizeof(pid_t) * (max_clients + 16));
- new_client_tags = malloc(sizeof(char *) * (max_clients + 16));
- if (new_client_fds && new_client_pids && new_client_tags) {
- memcpy(new_client_fds, client_fds, max_clients * sizeof(int));
- memcpy(new_client_pids, client_pids, max_clients * sizeof(pid_t));
- memcpy(new_client_tags, client_tags, max_clients * sizeof(char *));
- free(client_fds);
- free(client_pids);
- free(client_tags);
+ new_clients = malloc(sizeof(*new_clients) * (max_clients + 16));
+ if (new_clients) {
+ memcpy(new_clients, clients, max_clients * sizeof(*clients));
+ free(clients);
for (i = max_clients; i < max_clients + 16; ++i) {
- new_client_fds[i] = -1;
- new_client_pids[i] = 0;
- new_client_tags[i] = 0;
+ new_clients[i].fd = -1;
+ new_clients[i].pid = 0;
+ new_clients[i].tag = NULL;
+ new_clients[i].program = NULL;
}
- client_fds = new_client_fds;
- client_pids = new_client_pids;
- client_tags = new_client_tags;
-
- client_fds[max_clients] = fd;
- client_pids[max_clients] = 0;
- client_tags[max_clients] = 0;
+ clients = new_clients;
+ clients[max_clients].fd = fd;
+ clients[max_clients].pid = 0;
+ clients[max_clients].tag = NULL;
+ clients[max_clients].program = NULL;
highest_client = max_clients + 1;
max_clients += 16;
++active_clients;
} else {
- /* if something got allocated, free it */
- free(new_client_fds);
- free(new_client_pids);
- free(new_client_tags);
pseudo_diag("error allocating new client, fd %d\n", fd);
close(fd);
}
@@ -239,16 +233,24 @@ open_client(int fd) {
*/
static void
close_client(int client) {
- pseudo_debug(2, "lost client %d [%d], closing fd %d\n", client, client_pids[client], client_fds[client]);
+ pseudo_debug(2, "lost client %d [%d], closing fd %d\n", client,
+ clients[client].pid, clients[client].fd);
/* client went away... */
- close(client_fds[client]);
- client_fds[client] = -1;
- free(client_tags[client]);
- client_tags[client] = 0;
- client_pids[client] = 0;
+ if (client > highest_client || client <= 0) {
+ pseudo_diag("tried to close client %d (highest is %d)\n",
+ client, highest_client);
+ return;
+ }
+ close(clients[client].fd);
+ clients[client].fd = -1;
+ free(clients[client].tag);
+ free(clients[client].program);
+ clients[client].pid = 0;
+ clients[client].tag = NULL;
+ clients[client].program = NULL;
--active_clients;
if (client == highest_client)
- while (client_fds[highest_client] != -1 && highest_client > 0)
+ while (clients[highest_client].fd != -1 && highest_client > 0)
--highest_client;
}
@@ -259,34 +261,50 @@ serve_client(int i) {
pseudo_msg_t *in;
int rc;
- pseudo_debug(2, "message from client %d [%d:%s] fd %d\n",
- i, (int) client_pids[i],
- client_tags[i] ? client_tags[i] : "NO TAG",
- client_fds[i]);
- in = pseudo_msg_receive(client_fds[i]);
+ pseudo_debug(2, "message from client %d [%d:%s - %s] fd %d\n",
+ i, (int) clients[i].pid,
+ clients[i].program ? clients[i].program : "???",
+ clients[i].tag ? clients[i].tag : "NO TAG",
+ clients[i].fd);
+ in = pseudo_msg_receive(clients[i].fd);
if (in) {
char *response_path = 0;
pseudo_debug(4, "got a message (%d): %s\n", in->type, (in->pathlen ? in->path : "<no path>"));
/* handle incoming ping */
- if (in->type == PSEUDO_MSG_PING && !client_pids[i]) {
- pseudo_debug(2, "new client: %d -> %d\n",
+ if (in->type == PSEUDO_MSG_PING && !clients[i].pid) {
+ pseudo_debug(2, "new client: %d -> %d",
i, in->client);
- client_pids[i] = in->client;
+ clients[i].pid = in->client;
if (in->pathlen) {
- free(client_tags[i]);
- client_tags[i] = strdup(in->path);
+ size_t proglen;
+ proglen = strlen(in->path);
+
+ pseudo_debug(2, " <%s>", in->path);
+ free(clients[i].program);
+ clients[i].program = malloc(proglen + 1);
+ if (clients[i].program) {
+ snprintf(clients[i].program, proglen + 1, "%s", in->path);
+ }
+ if (in->pathlen > proglen) {
+ pseudo_debug(2, " [%s]", in->path + proglen + 1);
+ clients[i].tag = malloc(in->pathlen - proglen);
+ if (clients[i].tag)
+ snprintf(clients[i].tag, in->pathlen - proglen,
+ "%s", in->path + proglen + 1);
+ }
}
+ pseudo_debug(2, "\n");
}
/* sanity-check client ID */
- if (in->client != client_pids[i]) {
+ if (in->client != clients[i].pid) {
pseudo_debug(1, "uh-oh, expected pid %d for client %d, got %d\n",
- (int) client_pids[i], i, in->client);
+ (int) clients[i].pid, i, in->client);
}
/* regular requests are processed in place by
* pseudo_server_response.
*/
if (in->type != PSEUDO_MSG_SHUTDOWN) {
- if (pseudo_server_response(in, client_tags[i])) {
+ if (pseudo_server_response(in, clients[i].program, clients[i].tag)) {
in->type = PSEUDO_MSG_NAK;
} else {
in->type = PSEUDO_MSG_ACK;
@@ -312,8 +330,8 @@ serve_client(int i) {
in->fd = active_clients - 2;
s = response_path;
for (j = 1; j <= highest_client; ++j) {
- if (client_fds[j] != -1 && j != i) {
- s += snprintf(s, 8, "%d ", (int) client_pids[j]);
+ if (clients[j].fd != -1 && j != i) {
+ s += snprintf(s, 8, "%d ", (int) clients[j].pid);
}
}
in->pathlen = (s - response_path) + 1;
@@ -328,7 +346,7 @@ serve_client(int i) {
}
if ((rc = pseudo_msg_send(clients[i].fd, in, -1, response_path)) != 0)
pseudo_debug(1, "failed to send response to client %d [%d]: %d (%s)\n",
- i, (int) client_pids[i], rc, strerror(errno));
+ i, (int) clients[i].pid, rc, strerror(errno));
rc = in->op;
free(response_path);
return rc;
@@ -336,7 +354,7 @@ serve_client(int i) {
/* this should not be happening, but the exceptions aren't
* being detected in select() for some reason.
*/
- pseudo_debug(2, "client %d: no message\n", (int) client_pids[i]);
+ pseudo_debug(2, "client %d: no message\n", (int) clients[i].pid);
close_client(i);
return 0;
}
@@ -358,17 +376,16 @@ pseudo_server_loop(void) {
int fd;
int loop_timeout = pseudo_server_timeout;
- client_fds = malloc(sizeof(int) * 16);
- client_pids = malloc(sizeof(pid_t) * 16);
- client_tags = malloc(sizeof(char *) * 16);
+ clients = malloc(16 * sizeof(*clients));
- client_fds[0] = listen_fd;
- client_pids[0] = getpid();
+ clients[0].fd = listen_fd;
+ clients[0].pid = getpid();
for (i = 1; i < 16; ++i) {
- client_fds[i] = -1;
- client_pids[i] = 0;
- client_tags[i] = 0;
+ clients[i].fd = -1;
+ clients[i].pid = 0;
+ clients[i].tag = NULL;
+ clients[i].program = NULL;
}
active_clients = 1;
@@ -380,14 +397,14 @@ pseudo_server_loop(void) {
pseudo_diag("got into loop with no valid listen fd.\n");
exit(1);
}
- pdb_log_msg(SEVERITY_INFO, NULL, NULL, "server started (pid %d)", getpid());
+ pdb_log_msg(SEVERITY_INFO, NULL, NULL, NULL, "server started (pid %d)", getpid());
FD_ZERO(&reads);
FD_ZERO(&writes);
FD_ZERO(&events);
- FD_SET(client_fds[0], &reads);
- FD_SET(client_fds[0], &events);
- max_fd = client_fds[0];
+ FD_SET(clients[0].fd, &reads);
+ FD_SET(clients[0].fd, &events);
+ max_fd = clients[0].fd;
timeout = (struct timeval) { .tv_sec = LOOP_DELAY, .tv_usec = 0 };
/* EINTR tends to come from profiling, so it is not a good reason to
@@ -414,12 +431,12 @@ pseudo_server_loop(void) {
} else if (rc > 0) {
loop_timeout = pseudo_server_timeout;
for (i = 1; i <= highest_client; ++i) {
- if (client_fds[i] == -1)
+ if (clients[i].fd == -1)
continue;
- if (FD_ISSET(client_fds[i], &events)) {
+ if (FD_ISSET(clients[i].fd, &events)) {
/* this should happen but doesn't... */
close_client(i);
- } else if (FD_ISSET(client_fds[i], &reads)) {
+ } else if (FD_ISSET(clients[i].fd, &reads)) {
struct timeval tv1, tv2;
int op;
gettimeofday(&tv1, NULL);
@@ -440,8 +457,8 @@ pseudo_server_loop(void) {
break;
}
if (!(die_peacefully || die_forcefully) &&
- (FD_ISSET(client_fds[0], &events) ||
- FD_ISSET(client_fds[0], &reads))) {
+ (FD_ISSET(clients[0].fd, &events) ||
+ FD_ISSET(clients[0].fd, &reads))) {
len = sizeof(client);
if ((fd = accept(listen_fd, (struct sockaddr *) &client, &len)) != -1) {
pseudo_debug(2, "new client fd %d\n", fd);
@@ -456,31 +473,31 @@ pseudo_server_loop(void) {
getpid(), messages,
(double) message_time.tv_sec +
(double) message_time.tv_usec / 1000000.0);
- pdb_log_msg(SEVERITY_INFO, NULL, NULL, "server %d exiting: handled %d messages in %.4f seconds",
+ pdb_log_msg(SEVERITY_INFO, NULL, NULL, NULL, "server %d exiting: handled %d messages in %.4f seconds",
getpid(), messages,
(double) message_time.tv_sec +
(double) message_time.tv_usec / 1000000.0);
- close(client_fds[0]);
+ close(clients[0].fd);
exit(0);
}
FD_ZERO(&reads);
FD_ZERO(&writes);
FD_ZERO(&events);
- FD_SET(client_fds[0], &reads);
- FD_SET(client_fds[0], &events);
- max_fd = client_fds[0];
+ FD_SET(clients[0].fd, &reads);
+ FD_SET(clients[0].fd, &events);
+ max_fd = clients[0].fd;
/* current_clients is a sanity check; note that for
* purposes of select(), the server is one of the fds,
* and thus, "a client".
*/
current_clients = 1;
for (i = 1; i <= highest_client; ++i) {
- if (client_fds[i] != -1) {
+ if (clients[i].fd != -1) {
++current_clients;
- FD_SET(client_fds[i], &reads);
- FD_SET(client_fds[i], &events);
- if (client_fds[i] > max_fd)
- max_fd = client_fds[i];
+ FD_SET(clients[i].fd, &reads);
+ FD_SET(clients[i].fd, &events);
+ if (clients[i].fd > max_fd)
+ max_fd = clients[i].fd;
}
}
if (current_clients != active_clients) {