Track number of clients using just the queue

This commit is contained in:
Christopher Wellons
2019-02-03 18:32:24 -05:00
parent dbb2174b65
commit 516d0cd78c

View File

@@ -124,12 +124,14 @@ client_destroy(struct client *client)
struct queue { struct queue {
struct client *head; struct client *head;
struct client *tail; struct client *tail;
int length;
}; };
static void static void
queue_init(struct queue *q) queue_init(struct queue *q)
{ {
q->head = q->tail = 0; q->head = q->tail = 0;
q->length = 0;
} }
static struct client * static struct client *
@@ -142,6 +144,7 @@ queue_remove(struct queue *q, int fd)
struct client **prev = &q->head; struct client **prev = &q->head;
for (c = q->head; c; prev = &c->next, c = c->next) { for (c = q->head; c; prev = &c->next, c = c->next) {
if (c->fd == fd) { if (c->fd == fd) {
q->length--;
if (q->tail == c) if (q->tail == c)
q->tail = 0; q->tail = 0;
*prev = c->next; *prev = c->next;
@@ -161,6 +164,7 @@ queue_append(struct queue *q, struct client *c)
q->tail->next = c; q->tail->next = c;
q->tail = c; q->tail = c;
} }
q->length++;
} }
static void static void
@@ -173,6 +177,7 @@ queue_destroy(struct queue *q)
client_destroy(dead); client_destroy(dead);
} }
q->head = q->tail = 0; q->head = q->tail = 0;
q->length = 0;
} }
struct pollvec { struct pollvec {
@@ -473,7 +478,6 @@ server_create(int port)
if (s == -1) die(); if (s == -1) die();
/* Socket options are best effort, allowed to fail */ /* Socket options are best effort, allowed to fail */
value = 1; value = 1;
r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
logmsg(LOG_DEBUG, "setsockopt(SO_REUSEADDR, true) = %d", r); logmsg(LOG_DEBUG, "setsockopt(SO_REUSEADDR, true) = %d", r);
@@ -559,18 +563,16 @@ main(int argc, char **argv)
die(); die();
} }
int nclients = 0;
struct queue queue[1]; struct queue queue[1];
queue_init(queue); queue_init(queue);
struct pollvec pollvec[1]; struct pollvec pollvec[1];
pollvec_init(pollvec); pollvec_init(pollvec);
int server = server_create(config.port);
unsigned long rng = uepoch(); unsigned long rng = uepoch();
int server = server_create(config.port);
while (running) { while (running) {
if (reload) { if (reload) {
/* Configuration reload requested (SIGHUP) */ /* Configuration reload requested (SIGHUP) */
@@ -586,7 +588,7 @@ main(int argc, char **argv)
/* Enqueue the listening socket first */ /* Enqueue the listening socket first */
pollvec_clear(pollvec); pollvec_clear(pollvec);
if (nclients < config.max_clients) if (queue->length < config.max_clients)
pollvec_push(pollvec, server, POLLIN); pollvec_push(pollvec, server, POLLIN);
else else
pollvec_push(pollvec, -1, POLLIN); pollvec_push(pollvec, -1, POLLIN);
@@ -605,7 +607,7 @@ main(int argc, char **argv)
/* Wait for next event */ /* Wait for next event */
logmsg(LOG_DEBUG, "poll(%zu, %d)%s", pollvec->fill, timeout, logmsg(LOG_DEBUG, "poll(%zu, %d)%s", pollvec->fill, timeout,
nclients >= config.max_clients ? " (no accept)" : ""); queue->length >= config.max_clients ? " (no accept)" : "");
int r = poll(pollvec->fds, pollvec->fill, timeout); int r = poll(pollvec->fds, pollvec->fill, timeout);
logmsg(LOG_DEBUG, "= %d", r); logmsg(LOG_DEBUG, "= %d", r);
if (r == -1) { if (r == -1) {
@@ -628,10 +630,10 @@ main(int argc, char **argv)
switch (errno) { switch (errno) {
case EMFILE: case EMFILE:
case ENFILE: case ENFILE:
config.max_clients = nclients; config.max_clients = queue->length;
logmsg(LOG_INFO, logmsg(LOG_INFO,
"MaxClients %d", "MaxClients %d",
nclients); queue->length);
break; break;
case ECONNABORTED: case ECONNABORTED:
case EINTR: case EINTR:
@@ -651,10 +653,9 @@ main(int argc, char **argv)
fprintf(stderr, "endlessh: warning: out of memory\n"); fprintf(stderr, "endlessh: warning: out of memory\n");
close(fd); close(fd);
} }
nclients++;
logmsg(LOG_INFO, "ACCEPT host=%s port=%d fd=%d n=%d/%d", logmsg(LOG_INFO, "ACCEPT host=%s port=%d fd=%d n=%d/%d",
client->ipaddr, client->port, client->fd, client->ipaddr, client->port, client->fd,
nclients, config.max_clients); queue->length, config.max_clients);
queue_append(queue, client); queue_append(queue, client);
} }
} }
@@ -667,20 +668,24 @@ main(int argc, char **argv)
if (revents & POLLHUP) { if (revents & POLLHUP) {
client_destroy(client); client_destroy(client);
nclients--;
} else if (revents & POLLOUT) { } else if (revents & POLLOUT) {
char line[256]; char line[256];
int len = randline(line, config.max_line_length, &rng); int len = randline(line, config.max_line_length, &rng);
/* Don't really care if send is short */ for (;;) {
ssize_t out = send(fd, line, len, MSG_DONTWAIT); /* Don't really care if send is short */
if (out < 0) ssize_t out = send(fd, line, len, MSG_DONTWAIT);
client_destroy(client); if (out == -1 && errno == EINTR) {
else { continue; /* try again */
logmsg(LOG_DEBUG, "send(%d) = %d", fd, (int)out); } else if (out == -1) {
client->bytes_sent += out; client_destroy(client);
client->send_next = uepoch() + config.delay; } else {
queue_append(queue, client); logmsg(LOG_DEBUG, "send(%d) = %d", fd, (int)out);
client->bytes_sent += out;
client->send_next = uepoch() + config.delay;
queue_append(queue, client);
break;
}
} }
} }
} }